是 C # 中的 bool 读/写原子

在 C # 中访问 布尔字段是原子的吗:

class Foo
{
private bool _bar;


//... in some function on any thread (or many threads)
_bar = true;


//... same for a read
if (_bar) { ... }
}
66957 次浏览

Yes.

Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types.

as found in C# Language Spec.

Edit: It's probably also worthwhile understanding the volatile keyword.

bool accesses are indeed atomic, but that isn't the whole story.

You don't have to worry about reading a value that is 'incompletely written' - it isn't clear what that could possibly mean for a bool in any case - but you do have to worry about processor caches, at least if details of timing are an issue. If thread #1 running on core A has your _bar in cache, and _bar gets updated by thread #2 running on another core, thread #1 will not see the change immediately unless you add locking, declare _bar as volatile, or explicitly insert calls to Thread.MemoryBarrier() to invalidate the cached value.

As stated above, bool is atomic, but you still need to remember that it also depends on what you want to do with it.

if(b == false)
{
//do something
}

is not an atomic operation, meaning that the value of b could change before the current thread executes the code after the if statement.

the approach I have used, and I think is correct, is

volatile bool b = false;


.. rarely signal an update with a large state change...


lock b_lock
{
b = true;
//other;
}


... another thread ...


if(b)
{
lock b_lock
{
if(b)
{
//other stuff
b = false;
}
}
}

the goal was basically to avoid having to repetively lock an object on every iteration just to check if we needed to lock it in order to provide a large amount of state change information which occurs rarely. I think this approach works. And if absolute consistancy is required, I think volatile would be appropriate on the b bool.