William
William

Reputation: 3395

Thread-Safe Properties in C#

I know that this subject is slightly "Played Out", but I am still terribly confused. I have a class with properties that will be updates by multiple threads and I am trying to allow the properties to be updated in a Threadsafe manner.

Below, I have included a few examples of what I have tried thus far (the class is contained within a BindingList so its properties call a PropertyChangingEventHandler event).

Method 1 - Doubles

private double _Beta;
public double Beta
{
    get
    {
        return _Beta;
    }
}

private readonly BetaLocker = new object();
public void UpdateBeta(double Value)
{
    lock (BetaLocker)
    {
        _Beta = Value;
        NotifyPropertyChanged("Beta");
    }
}

Method 2 - Ints

private int _CurrentPosition;
public int CurrentPosition
{
    get
    {
        return _CurrentPosition;
    }
}

public void UpdatePosition(int UpdateQuantity)
{
    Interlocked.Add(ref _CurrentPosition, UpdateQuantity);
    NotifyPropertyChanged("CurrentPosition");
}

Upvotes: 3

Views: 2004

Answers (1)

Kiril
Kiril

Reputation: 40345

Basically - is the current way that I am creating properties completely threadsafe for both ints and doubles?

You have to ask yourself what it means to be Thread Safe (yes, it's a link to wikipedia and it's blacked out ^_^):

A piece of code is thread-safe if it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time. There are various strategies for making thread-safe data structure

So now you have to determine if your code guarantees safe execution if executed by multiple threads: the quick answer is that both of your code samples are thread safe! However (and this is a big one), you also have to consider the usage of the object and determine if it is Thread Safe also... here is an example:

if(instance.Beta==10.0)
{
   instance.UpdateBeta(instance.Beta*10.0);
}

// what's instance.Beta now?

In this case you have absolutely no guarantee that Beta will be 100.0 because beta could have changed after you checked it. Imagine this situation:

Thread 2: UpdateBeta(10.0)
Thread 1: if(Beta == 10.00)
Thread 2: UpdateBeta(20.0)
Thread 1: UpdateBeta(Beta*10.0)
// Beta is now 200.0!!! 

The quick and dirty way to fix this is to use a double-checked lock:

if(instance.Beta==10.0)
{
    lock(instance)
    {
        if(instance.Beta==10.0)
        {
            instance.UpdateBeta(instance.Beta*10.0);
        }
    }
}

The same is true for CurrentPosition.

Upvotes: 3

Related Questions