开发者

Volatile Variables and Happens before ordering [duplicate]

This question already has answers here: Java memory model: volatile variables and happens-before (3 answers) Closed 7 years ago.

I have two threads:

Thread:1

a = 1;
x = b;

Thread:2

b = 1
y = a

Here a and b are declared volatile. I did not understand how a "happens-before" edge is created between a = 1; and y = a; and between x = b; and b = 1;

I understand that by using volatile variable one can prevent reading stale values from thread cache. But how can a volatile variable ensure happens-before ordering.

Specifically, 开发者_JAVA技巧I did not understand this:

a write to a volatile field happens before every subsequent read of the same field.

Hoe does it work?


a write to a volatile field happens before every subsequent read of the same field.

The important word here is "subsequent".

Here's the relevant bit of the Java Language Specification 17.4.4 Synchronization Order:

Every execution has a synchronization order. A synchronization order is a total order over all of the synchronization actions of an execution. For each thread t, the synchronization order of the synchronization actions (§17.4.2) in t is consistent with the program order (§17.4.3) of t. Synchronization actions induce the synchronized-with relation on actions, defined as follows:

  • [...]
  • A write to a volatile variable (§8.3.1.4) v synchronizes-with all subsequent reads of v by any thread (where subsequent is defined according to the synchronization order).

Note the last part. So it's saying that if you consider any total ordering of the actions of the program, any read of a volatile variable which comes later in that total ordering than a write can't "miss" the write.


To analyze, first you list all possible synchronization orders. they must be consistent with programming order. In your example, there are 6 possible orders.

 1       2       3       4       5       6
w(a)    w(a)    w(b)    w(a)    w(b)    w(b) 
r(b)    w(b)    w(a)    w(b)    w(a)    r(a)
w(b)    r(b)    r(b)    r(a)    r(a)    w(a)
r(a)    r(a)    r(a)    r(b)    r(b)    r(b)

Each order establishes some happens-before relations. In (1), we have w(a) happens-before r(a). In (6), we have w(b) happens-before r(b). In (2)-(5), we have both.

For every possible order, given the happens-before relations established by it, you need to analyze the execution to make sure it does what you want.

If that sounds too hard, it is. In real life, we usually limit ourselves with simpler situations, where only one object is locked/released, or only one volatile variable is read and write. Then it's not too complex.


a write to a volatile field happens before every subsequent read of the same field.

This text is what's confusing. It limits the happens-before relationship to writes that happen-before the read! It only says that reads that happen after, actually happen after.

In other words, what it's trying to say is that the read doesn't happen during the write, and also that if there are other happens-before relationships that cause the read to happen after the write, that the read will have the value of that write.

See the JLS section 17.4.4 Synchronization Order which defines the word "subsequent" in this context.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜