多线程和布尔值

时间:2010-04-12 08:42:29

标签: .net multithreading

我有一个类包含一个像这样的布尔字段:

public class MyClass
{
    private bool boolVal;
    public bool BoolVal
    {
        get { return boolVal; }
        set { boolVal = value; }
    }
}

可以使用该属性从许多线程读取和写入该字段。我的问题是我是否应该使用锁定语句来阻止getter和setter?或者我应该只使用volatile关键字并保存锁定?或者我应该完全忽略多线程,因为获取和设置布尔值原子?

的问候,

2 个答案:

答案 0 :(得分:9)

这里有几个问题。

简单第一。是的,读取和写入布尔变量是一种原子操作。 (澄清:我的意思是读取和写入操作本身是布尔值的原子操作,而不是读取写入,当然生成两个操作,它们一起不会是原子的)

但是,除非您采取额外步骤,否则编译器可能会优化此类读取或写入操作,或者移动操作,这可能会使您的代码与您的操作不同。

将字段标记为volatile意味着操作不会被优化掉,该指令基本上说编译器不应该假设此字段中的值与前一个相同,即使它只是读取它在上一条指令中。

但是,在多核和多CPU计算机上,不同的核心和cpu可能在其缓存中具有不同的字段值,因此您添加了lock { }子句或任何其他强制内存障碍的子句。这将确保字段值在核心之间保持一致。此外,读取和写入不会超出代码中的内存障碍,这意味着您可以预测操作发生的位置。

因此,如果您怀疑或知道该字段将被写入多个线程并从多个线程读取,我肯定会添加锁定和易失性。

请注意,我不是多线程的专家,我能够拥有自己的,但我通常会在防守方面进行编程。可能(我认为很有可能)你可以实现一些不使用锁的东西(有许多无锁构造),但遗憾的是我在这个主题中没有足够的经验来处理这些事情。因此,我的建议是添加lock子句和volatile指令。

答案 1 :(得分:2)

单独使用volatile是不够的,并且用于不同的目的,锁定应该没问题,但最终它取决于是否有人要在MyClass中设置boolVal,谁知道,你可能有一个工作线程在那里旋转。它还取决于你如何在内部使用boolVal。您可能还需要其他地方的保护。如果你问我,如果你不是DEAD SURE你将在多个线程中使用MyClass,那么它甚至不值得考虑它。

P.S。您可能还想阅读this section