在C#中,bool类型的线程安全
在C#中,bool类型的线程安全
我对这个主题感到非常困惑—读取/切换bool值是否是线程安全的。
// case one, nothing private bool v1; public bool V1 { get { return v1; } set { v1 = value; } } // case two, with Interlocked on set private int v2; public int V2 { get { return v2; } set { Interlocked.Exchange(ref v2, value); } } // case three, with lock on set private object fieldLock = new object(); private bool v3; public bool V3 { get { return v3; } set { lock (fieldLock) v3 = value; } }
它们全部都是线程安全的吗?
编辑
根据我所阅读的(点击), 布尔原子性不能保证它是线程安全的。那么volatile
类型是否有帮助?
admin 更改状态以发布 2023年5月21日
不是所有的都是线程安全的。
第一种情况实际上并不完全线程安全,或者更好地说 - 它完全不是线程安全的。 即使布尔运算是原子性的,变量值也可能存储在缓存中,因此,由于在多核CPU中每个核心都有自己的缓存,所以该值可能会被破坏。
更进一步,编译器和CPU可以执行一些内部优化,包括指令重排序,这可能会对您程序的逻辑产生负面影响。
您可以添加 volatile
关键字,通知编译器此字段在多线程环境中使用。这将解决缓存和指令重排序的问题,但不为您提供真正的“线程安全”代码(因为写入操作仍然不会同步)。 此外,volatile
不能应用于本地变量。
因此,在处理多线程时,您始终需要使用一些线程同步技术来保护有价值的资源。
有关更多信息,请阅读这篇 回答,其中有关于不同技术的更深入的解释。(该示例是关于int
,但实际上并不重要,它描述了一般方法。)
虽然有点晚,但对其他人应该有用。
你可以按照以下方式实现自己的线程安全布尔变量:
// default is false, set 1 for true. private int _threadSafeBoolBackValue = 0; public bool ThreadSafeBool { get { return (Interlocked.CompareExchange(ref _threadSafeBoolBackValue, 1, 1) == 1); } set { if (value) Interlocked.CompareExchange(ref _threadSafeBoolBackValue, 1, 0); else Interlocked.CompareExchange(ref _threadSafeBoolBackValue, 0, 1); } }
一定要在任何地方使用Property,不要直接访问int
变量。