[concurrency-interest] Volatile array and Wait

Chris Purcell chris.purcell.39 at gmail.com
Wed Oct 19 13:34:33 EDT 2005


Okay, I've thought this out a bit. My analysis follows.

1) A volatile write should have the same semantics as a monitor release
2) A volatile read should have the same semantics as a monitor acquire

A monitor release ensures all preceding writes are visible before it 
commits. A monitor acquire prevents subsequent read operations from 
passing across it. These give the appearance of sequential execution of 
critical sections.

We wish to attach release semantics to our write to b[22]. Any 
preceding writes must be visible to any reader who subsequently 
performs an acquire.

If b[22] is *followed* by a volatile write/monitor release, there is a 
period of time in which concurrent updates may see the new value of 
b[22] but not any preceding writes despite performing an acquire in 
between: namely, the time between the write to b[22] committing and the 
release barrier.

Unfortunately, if the write to b[22] is *preceded* by a volatile 
write/monitor release, the write to b[22] can be moved before the 
release barrier (either by compiler or hardware) since it is not itself 
volatile; once again there is a period of time in which concurrent 
updates may see the new value of b[22] then do an acquire, yet still 
not see any preceding writes, namely the time between the write to 
b[22] committing and the release barrier.

However, if one could precede the write to b[22] with a release barrier 
then a subsequent volatile read of a value on which the write operation 
is dependent, then the write can no longer be reordered before the 
barrier. The read of b should be sufficient for this.

Hence the correct code is:

b = b; // Release barrier
b[22] = x; // Subsequent acquire barrier followed by dependent write

as I suggested.

Attaching a monitor acquire to the read of b[22] is more problematic. 
The acquire barrier must occur *after* the read of b[22] to prevent 
subsequent reads from being reordered incorrectly. To do this, one must 
make the acquire barrier *dependent* on the read of b[22], or risk them 
being reordered. In assembler, this would be trivial, as one could fake 
a volatile read that was dependent on the value of b[22]. I'm not clear 
how to do this reliably in Java, as fake dependencies risk being 
optimised away. The following might work, but might not:

x = b[22];
if (x < 1000)
    temp = b;
else
    temp = some_other_volatile;

In conclusion, don't try and emulate volatility.

Cheers,
Chris



More information about the Concurrency-interest mailing list