tags:

views:

69

answers:

3

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, I did not understand this:

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

Hoe does it work?

+2  A: 

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 on Synchronization Order which defines the word "subsequent" in this context.

Mark Peters
+3  A: 

The important word here is "subsequent".

Here's the relevant bit of the spec:

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.

Jon Skeet
"*For each thread t*, the synchronization order of the synchronization actions..." volatile by itself does not determine synchronization order between threads does it?
pst
I too have the same question. Finding java spec a bit cryptic.
iJeeves
@pst: Volatile operates on the *total* order, rather than the order for a specific thread. It effectively means that a thread can't read a volatile variable without checking whether any other thread has performed a write.
Jon Skeet
+2  A: 

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.

irreputable