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

标签 c# .net multithreading properties thread-safety

我正在尝试在 C# 中创建线程安全属性,我想确保我在正确的路径上 - 这是我所做的 -

private readonly object AvgBuyPriceLocker = new object();
private double _AvgBuyPrice;
private double AvgBuyPrice 
{
    get
    {
        lock (AvgBuyPriceLocker)
        {
            return _AvgBuyPrice;
        }
    }
    set
    {
        lock (AvgBuyPriceLocker)
        {
            _AvgBuyPrice = value;
        }
    }
}

阅读这篇文章,似乎这不是正确的做法 -

C# thread safety with get/set

然而,这篇文章似乎另有建议,

http://www.codeproject.com/KB/cs/Synchronized.aspx

有没有人有更明确的答案?

编辑:

我想为此属性执行 Getter/Setter 的原因是 b/c 我实际上希望它在设置时触发一个事件 - 所以代码实际上是这样的 -

public class PLTracker
{

    public PLEvents Events;

    private readonly object AvgBuyPriceLocker = new object();
    private double _AvgBuyPrice;
    private double AvgBuyPrice 
    {
        get
        {
            lock (AvgBuyPriceLocker)
            {
                return _AvgBuyPrice;
            }
        }
        set
        {
            lock (AvgBuyPriceLocker)
            {
                Events.AvgBuyPriceUpdate(value);
                _AvgBuyPrice = value;
            }
        }
    }
}

public class PLEvents
{
    public delegate void PLUpdateHandler(double Update);
    public event PLUpdateHandler AvgBuyPriceUpdateListener;

    public void AvgBuyPriceUpdate(double AvgBuyPrice)
    {
        lock (this)
        {
            try
            {
                if (AvgBuyPriceUpdateListener!= null)
                {
                    AvgBuyPriceUpdateListener(AvgBuyPrice);
                }
                else
                {
                    throw new Exception("AvgBuyPriceUpdateListener is null");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

我对确保我的代码线程安全还很陌生,所以如果我以完全错误的方式进行处理,请随时告诉我!

最佳答案

如您所写,锁是毫无意义的。例如,读取变量的线程将:

  1. 获取锁。
  2. 读取值。
  3. 释放锁。
  4. 以某种方式使用读取的值。

在第 3 步之后,没有什么可以阻止另一个线程修改该值。由于 .NET 中的变量访问是原子的(请参阅下面的警告),锁在这里实际上并没有实现太多:只是增加了开销。与解锁示例对比:

  1. 读取值。
  2. 以某种方式使用读取的值。

另一个线程可能会更改第 1 步和第 2 步之间的值,这与锁定的示例没有什么不同。

如果要确保在进行某些处理时状态不会更改,则必须在锁的上下文中读取值并使用该值进行处理:

  1. 获取锁。
  2. 读取值。
  3. 以某种方式使用读取的值。
  4. 释放锁。

话虽如此,有些情况下您需要在访问变量时进行锁定。这些通常是由于底层处理器的原因:例如,double 变量不能在 32 位机器上作为单个指令读取或写入,因此您必须锁定(或使用替代策略)以确保不读取损坏的值。

关于c# - C# 中的线程安全属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7161413/

相关文章:

.net - 使用 Azure ApplicationInsights 时,在哪里可以找到 TelemetryClient.TrackEvent() 的输出日志?

c# - 数组是否实现了 IEnumerable<T>?

java - 当子类从线程父类扩展时,我们是否覆盖运行方法

java - Dagger 2 中的@Singleton 线程安全吗?

c# - 如何在开发Web应用程序和桌面应用程序之间做出决定

c# - 尝试打开 Webview 时崩溃 - Xamarin.Forms.Platform.Android.WebViewRender+WebClient

c# - 防止C#中的重复代码

c# - C# 有办法给我一个不可变的字典吗?

c - 使用多线程时如何检测数据丢失的位置

c# - 委托(delegate) - 异常不会等到调用 EndInvoke()