在C#中访问bool字段原子? 特别是,我需要锁定:
1 2 3 4 5 6 7 8 9 10
| class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
} |
是。
Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types.
在C#语言规范中找到。
编辑:理解volatile关键字可能也值得。
如上所述bool是原子的,但你仍需要记住它还取决于你想用它做什么。
1 2 3 4
| if(b == false)
{
//do something
} |
不是
原子操作意味着b值可以在当前线程在if语句之后执行代码之前改变。
bool访问确实是原子的,但这不是全部。
您不必担心读取"未完全编写"的值 - 在任何情况下都不清楚boo可能意味着什么 - 但您必须担心处理器缓存,至少在时机是一个问题。如果在核心A上运行的线程#1在缓存中具有_bar,并且_bar由在另一个核心上运行的线程#2更新,则线程#1将不会立即看到更改,除非您添加锁定,声明_bar为volatile,或显式插入对Thread.MemoryBarrier()的调用以使缓存的值无效。
我使用的方法,我认为是正确的,是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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;
}
}
} |
目标基本上是避免必须在每次迭代时重复锁定一个对象,只是为了检查我们是否需要锁定它以便提供很少发生的大量状态变化信息。我认为这种方法有效。如果需要绝对的一致性,我认为挥发性在b bool上是合适的。