我对这个问题非常困惑--读/切换一个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; } }
它们都是安全的吗?
编辑
根据我所读到的(点击),bool的原子性并不保证它是线程安全的。那么volatile
类型有用吗?
发布于 2015-04-02 12:01:33
不,不是所有的都是线程安全的。
案例一实际上并不是完全线程安全,或者更好地说-它根本不是线程安全。即使布尔操作是原子的,变量值也可以存储在缓存中,因此,就像多核CPU中的每个内核都有自己的缓存一样,值也可能被破坏。
更进一步,编译器和CPU可以执行一些内部优化,包括指令重新排序,这会对程序的逻辑产生有害影响。
您可以添加volatile
关键字,通知编译器该字段在多线程上下文中使用。它将修复缓存和指令重新排序的问题,但不会给您真正的“线程安全”代码(因为写操作仍然不同步)。此外,volatile
不能应用于局部变量。
因此,在处理多线程时,您总是需要在宝贵的资源上使用一些线程同步技术。
要了解更多信息,请阅读这答案,它对不同的技术有一些更深入的解释。(例如,有关于int
的,但这并不重要,它描述了一般的方法。)
发布于 2018-03-12 11:04:36
有点晚了,但对其他人应该是有用的。
您可以通过以下方式实现您自己的线程安全布尔值:
// 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);
}
}
确保在任何地方都使用属性,永远不要直接访问int
变量。
发布于 2022-05-08 20:10:01
不,不是。但解决办法很容易。为了使线程安全(或者任何事情),很容易使用这样的锁定语句:
object locker = new object();
protected bool _somebool;
public bool Somebool
{
get
{
lock (locker)
return _somebool;
}
set
{
lock (locker)
_somebool = value;
}
}
现在您可以享受<T>
的线程安全了。
https://stackoverflow.com/questions/29411961
复制相似问题