13

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?

softwarematter
  • 28,015
  • 64
  • 169
  • 263
  • See this recent question and answer for a lot of relevant info: http://stackoverflow.com/questions/3964317/memory-barriers-and-coding-style-over-a-java-vm – andersoj Oct 19 '10 at 18:43

3 Answers3

16

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.

Gray
  • 115,027
  • 24
  • 293
  • 354
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • "*For each thread t*, the synchronization order of the synchronization actions..." volatile by itself does not determine synchronization order between threads does it? –  Oct 19 '10 at 17:47
  • I too have the same question. Finding java spec a bit cryptic. – softwarematter Oct 19 '10 at 18:04
  • 1
    @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 Oct 19 '10 at 18:21
  • @JonSkeet I read the JLS and I don't the `Synchronization Order` is the same as `Happends-before Order`, `Happens-before Order` applys when two conflicting accesses occurs. – khotyn Dec 09 '11 at 03:05
  • @JonSkeet as u said: "thread can't read a volatile variable without checking whether any other thread has performed a write." but what happens if one thread is in between of writing operation and second thread is reading it!! am i wrong ?? isn't it race condition with atomic operation ?? pls reply. – hardik Apr 02 '12 at 12:00
5

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
  • 44,725
  • 9
  • 65
  • 93
3

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.

reevesy
  • 3,452
  • 1
  • 26
  • 23
Mark Peters
  • 80,126
  • 17
  • 159
  • 190