C#中的线程安全属性

时间:2012-01-18 22:24:17

标签: c#-4.0 properties thread-safety

我知道这个主题稍微“玩了”,但我仍然非常困惑。我有一个类,其属性将由多个线程更新,我试图允许以Threadsafe方式更新属性。

下面,我已经包含了一些我迄今为止尝试过的示例(该类包含在BindingList中,因此其属性调用了PropertyChangingEventHandler事件)。

方法1 - 双打

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");
    }
}

方法2 - Ints

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

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

1 个答案:

答案 0 :(得分:3)

  

基本上 - 当前的方式是我为int和double创建完全线程安全的属性?

你必须问问自己Thread Safe意味着什么(是的,它是维基百科的链接,它被涂黑了^ _ ^):

  

如果一段代码仅以保证多个线程同时安全执行的方式操作共享数据结构,则它是线程安全的。有各种策略来制作线程安全的数据结构

所以现在你必须确定你的代码是否保证在多个线程执行时安全执行:快速回答是你的两个代码示例都是线程安全的! 然而(这是一个很大的问题),您还必须考虑对象的用法并确定它是否也是线程安全的......这是一个例子:

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

// what's instance.Beta now?

在这种情况下,您绝对无法保证Beta将为100.0,因为您检查后测试版可能已更改。想象一下这种情况:

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!!! 

解决此问题的快速而肮脏的方法是使用双重检查锁:

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

CurrentPosition也是如此。