多线程和布尔布尔、多线程

2023-09-03 03:32:10 作者:野心勃勃人

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

I have a class that contains a boolean field like this one:

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

字段可以读取和使用属性,从多个线程写入。我的问题是,如果我要栅栏的getter和setter与lock语句?或者我应该简单地使用volatile关键字,并保存锁定?或者我应该完全忽略,因为获取和设置布尔值原子多线程?

The field can be read and written from many threads using the property. My question is if I should fence the getter and setter with a lock statement? Or should I simply use the volatile keyword and save the locking? Or should I totally ignore multithreading since getting and setting boolean values atomic?

问候,

推荐答案

这里有几个问题。

简单的第一个。是的,读,写一个布尔变量是一个原子操作。 (说明的:我的意思是,读取和写入操作的自己的是一个基本操作的布尔值,不读书的和的写作,当然这种意愿产生两个操作,它们共同将不是原子)

The simple first. Yes, reading and writing a boolean variable is an atomic operation. (clarification: What I mean is that read and write operations by themselves are atomic operations for booleans, not reading and writing, that will of course generate two operations, which together will not be atomic)

不过,除非你采取额外的步骤,编译器可能会优化掉这样的阅读和写作,或四处移动的操作,这可能使你的code操作不同于你打算。

However, unless you take extra steps, the compiler might optimize away such reading and writing, or move the operations around, which could make your code operate differently from what you intend.

标记字段为挥发性意味着该操作不会被优化掉,该指令基本上说,编译器不应该承担该字段中的值是一样的在previous之一,即使它只是读它在previous指令。

Marking the field as volatile means that the operations will not be optimized away, the directive basically says that the compiler should never assume the value in this field is the same as the previous one, even if it just read it in the previous instruction.

不过,在多核和multicpu的机器,不同的内核和CPU可能对领域的不同值的缓存,这样的话你添加一个锁定{} 条款,或其他任何强制内存屏障。这将确保该字段值是在整个芯一致。此外,读取和写入不会移动过去在code内存屏障,这意味着你必须predictability在操作发生。

However, on multicore and multicpu machines, different cores and cpus might have a different value for the field in their cache, and thus you add a lock { } clause, or anything else that forces a memory barrier. This will ensure that the field value is consistent across cores. Additionally, reads and writes will not move past a memory barrier in the code, which means you have predictability in where the operations happen.

因此​​,如果您怀疑或知道,这个领域将被写入,并从多个线程读取,我肯定会添加锁定和挥发性的组合。

So if you suspect, or know, that this field will be written to and read from multiple threads, I would definitely add locking and volatile to the mix.

请注意,我在多线程方面的专家,我能够保持我自己,但我通常编程防守。有可能(我会假设它极有可能),你可以实现的东西,不使用锁(也有很多无锁的结构),但遗憾的是我没有足够的经验这个主题来处理这些事情。因此,我的建议是添加既是锁定子句和挥发性指令。

Note that I'm no expert in multithreading, I'm able to hold my own, but I usually program defensively. There might (I would assume it is highly likely) that you can implement something that doesn't use a lock (there are many lock-free constructs), but sadly I'm not experienced enough in this topic to handle those things. Thus my advice is to add both a lock clause and a volatile directive.