开发者

volatile with release/acquire semantics

Since Java 5, the volatile keyword has release/acquire semantics to make side-effects visible to other threads (including assignments to non-volatile variables!). Take these two variables, for example:

int i;
volatile int v;

Note that i is a regular, non-volatile variable. Imagine thread 1 executing the following statements:

i = 42;
v = 0;

At some later point in开发者_如何学编程 time, thread 2 executes the following statements:

int some_local_variable = v;
print(i);

According to the Java memory model, the write of v in thread 1 followed by the read of v in thread 2 ensures that thread 2 sees the write to i executed in thread 1, so the value 42 is printed.

My question is: does volatile have the same release/acquire semantics in C#?


The semantics of "volatile" in C# are defined in sections 7.10 and 14.5.4 of the C# 6.0 specification. Rather than reproduce them here, I encourage you to look it up in the spec, and then decide that it is too complicated and dangerous to use "volatile", and go back to using locks. That's what I always do.

See "7.10 Execution order" and "14.5.4 Volatile fields" in the C# 6.0 specification.


In the C# 5.0 specification, see "3.10 Execution Order" and "10.5.3 Volatile Fields"


Well, I believe it ensures that if some_local_variable is read as 0 (due to the write to v), i will be read as 42.

The tricky part is "at some later point in time". While commonly volatility is talked about in terms of "flushing" writes, that's not how it's actually defined in the spec (either Java or C#).

From the C# 4 language spec, section 10.5.3:

For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the lock-statement (§8.12). These optimizations can be performed by the compiler, by the run-time system, or by hardware. For volatile fields, such reordering optimizations are restricted:

  • A read of a volatile field is called a volatile read. A volatile read has “acquire semantics”; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
  • A write of a volatile field is called a volatile write. A volatile write has “release semantics”; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.

There's then an example which is quite similar to yours, but conditional on the value read from the volatile variable.

And like Eric, I'd strongly avoid relying on volatile myself. It's hard to reason about, and best left to the Joe Duffy/Stephen Toubs of the world.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜