Skip to main content
 首页 » 编程设计

c#-4.0之C# 中的线程安全属性

2024年08月06日30sky-heaven

我知道这个话题有点“过时”,但我仍然非常困惑。我有一个类,其属性将由多个线程更新,并且我试图允许以线程安全的方式更新属性。

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

方法 1 - double

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 - 整数

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

请您参考如下方法:

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

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

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

所以现在您必须确定您的代码在由多个线程执行时是否保证安全执行:简单的答案是您的两个代码示例都是线程安全的! 但是(这是一个大问题),您还必须考虑对象的用法并确定它是否也是线程安全的......这是一个示例:

if(instance.Beta==10.0) 
{ 
   instance.UpdateBeta(instance.Beta*10.0); 
} 
 
// what's instance.Beta now? 

在这种情况下,您绝对不能保证 Beta 将为 100.0,因为 beta 可能在您检查后发生变化。想象一下这种情况:

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 也是如此。