C# 线程安全的静态成员

标签 c# .net multithreading atomic

我有一个带有静态成员的 C# 类,它从多个线程读取并在一个线程中写入。

据我所知Uint64读写并不是所有系统上的原子操作,所以我要手动保证线程安全。

我对如何做到这一点有一些想法。

  1. 使用原子包装类来实现,就像 C++ 中的 std::atomic 一样。在 C# 中是否有类似的实现?

  2. 对静态字段使用 volatile 修饰符。然而这是不允许的。为什么?

  3. 我最终做了以下事情:

    private static object tick_time_lock;
    private static UInt64 _currentTickTime;
    public static UInt64 CurrentTickTime 
    {
        get
        {
            return _currentTickTime;
        }
        set
        {
            lock (tick_time_lock)
            {
                _currentTickTime = value;
            }
        }
    }
    

这是使该字段线程安全的正确方法吗?

最佳答案

Is this the correct way of making this field thread-safe?

除非同步给定资源的所有 访问,否则监视器锁是没有意义的。锁定 set 访问器是毫无用处的,除非您还锁定了 get 访问器。正如您所说,UInt64 值的读写在所有平台上都不是原子的。如果在 set 访问器中仅写入第一个单词时,在 get 访问器中读取该字段会发生什么情况?你会得到一个撕裂的阅读。

Use the volatile modifier with static field. However this is not allowed. Why?

C# 语言设计者认为保证所有 volatile 字段访问都是原子的是有益的。作为权衡,您不能将任何 64 位字段声明为 volatile。我不确定为什么做出这个决定。也许他们想避免向一些 volatile 读/写操作添加“隐藏”开销,而是要求开发人员依赖框架级设施,如 Thread.Volatile[Read/Write](ref long) 来处理64 位值。

Do it with and atomic wrapper class, like std::atomic in c++. Is there something similar implemented in C#?

是的。通过System.Threading.Interlocked类暴露了框架级别的原子操作,包括ReadExchangeCompareExchange.

关于C# 线程安全的静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20205359/

相关文章:

c# - 线程安全的 List<T> 属性

c# - 在另一台计算机上运行 C# 程序时出现 System.IO.FileLoadException

c# - 如何从 aspx.cs 页面切换确认消息框

.net - VS2010 中的 Assert.AreEqual() 异常

c - 您如何查询 pthread 以查看它是否仍在运行?

objective-c - 将 NSProgress 与嵌套的 NSOperations 一起使用

c# - 使用特定用户帐户运行 Windows 应用程序

c# - 处理数千个 UDP 数据包并使用 Threads 将它们保存在远程数据库中的最佳方法是什么?

c# - 使用 MongoDB C# 驱动程序 2.0 的服务器端投影

Java 线程 GDB