在C#中,bool类型的线程安全

34 浏览
0 Comments

在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日
0
0 Comments

不是所有的都是线程安全的。

第一种情况实际上并不完全线程安全,或者更好地说 - 它完全不是线程安全的。 即使布尔运算是原子性的,变量值也可能存储在缓存中,因此,由于在多核CPU中每个核心都有自己的缓存,所以该值可能会被破坏。

更进一步,编译器和CPU可以执行一些内部优化,包括指令重排序,这可能会对您程序的逻辑产生负面影响。

您可以添加 volatile 关键字,通知编译器此字段在多线程环境中使用。这将解决缓存和指令重排序的问题,但不为您提供真正的“线程安全”代码(因为写入操作仍然不会同步)。 此外,volatile 不能应用于本地变量。

因此,在处理多线程时,您始终需要使用一些线程同步技术来保护有价值的资源。

有关更多信息,请阅读这篇 回答,其中有关于不同技术的更深入的解释。(该示例是关于int,但实际上并不重要,它描述了一般方法。)

0
0 Comments

虽然有点晚,但对其他人应该有用。

你可以按照以下方式实现自己的线程安全布尔变量:

// 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变量。

0