[concurrency-interest] "Volatile-like" guarantees

Vitaly Davidovich vitalyd at gmail.com
Wed Feb 2 16:02:14 EST 2011


In your example class Foo I think you meant setF to actually write x to f,
not read it.

In any case, the code you have is not sequentially consistent because the
write to non-volatile must happen before the volatile write, and the
corresponding non-volatile read must happen after the volatile read.  If you
do that, the JMM guarantees sequential consistency (data race is a separate
issue, as you mentioned).

The "piggybacking" of non-volatile read/writes through volatile ones happens
a lot in Java; it's just usually done indirectly by using some higher-level
constructs (locks, Java.utility.concurrent classes, etc).

Also the compiler is not allowed to, amongst other things, eliminate reads
or stores to volatile members so your assignment of zero shouldn't be a
problem (for a compliant jvm and static compiler).
On Feb 2, 2011 2:23 PM, "Niko Matsakis" <niko at alum.mit.edu> wrote:
> Hello everyone,
>
> I have a question about the Java Memory Model. I am trying to decide if
> it is possible to use a dummy volatile field, like the field v below, to
> get the same guarantees as an actual volatile field. In other words, is
> the class Foo shown here equivalent to a class where the the field f is
> declared volatile:
>> class Foo {
>> private volatile int v;
>> private int f;
>>
>> void setF(int x) {
>> v = 0; // Wv
>> x = f; // Wf
>> }
>>
>> int getF() {
>> int x = f; // Rf
>> int y = v; // Rv
>> return x;
>> }
>> }
> In particular, would code using the accessors shown above still be
> sequentially consistent, as it would be if "f" were volatile?
>
> Clearly, the program is not data-race free as defined by the JMM,
> because the write Wf does not happen before Rf. Nonetheless, I believe
> there is a guarantee very much like the one that volatile offers, which
> I will call "volatile-like":
>> If Rf sees the value written by Wf, then no subsequent read will see a
>> write that was overwritten before the write Wv occurred. More
>> formally, no read r that happens after Rv, which includes all reads in
>> the thread calling getF(), will see a write w that happens before Wv
>> where there exists another write w' such that w -> w' -> Wv.
> An informal argument can be found below [1]. I believe that this
> "volatile-like" guarantee implies sequential consistency, in the same
> way that the volatile guarantee would (argument [2] below). However, I
> ALSO believe that the JMM is fairly subtle, and I may well be missing
> something. :) Hence my e-mail to this list.
>
> One particular concern I have is the possibility that a compiler might
> observe that all the writes to the volatile field "v" are of the same
> value, 0, and therefore eliminated the field. (A similar example
> appears in the JMM paper I have been consulting). I believe however
> that this ought to be illegal by the JMM, as "v" is volatile and
> therefore induces happens-before relations in addition to carrying a
value.
>
> I thank all of you in advance, both for taking the time to read this
> e-mail and for any insight you may provide.
>
>
> regards,
> Niko
>
> -----
>
> [1] The argument that Rf/Wf have a "volatile-like" relationship is as
> follows:
>
> First, the only important cases are those where Rf sees the write Wf.
> This is because the "volatile-like" guarantees described above only
> concern what happens when Rf sees the write Wf. As the volatile
> accesses Wv and Rv are both synchronization actions, one must happen
> before the other in any particular execution. If Rv happens before Wv,
> then at the time when field f is read, Wf cannot be visible, because Rf
> -> Rv -> Wv -> Wf. Therefore, Rf cannot see the write Wf, and this case
> is not important.
>
> If Wv happens before Rv, then when Rf executes, it is possible that Wf
> has already been committed. In that case, Rf may legally see the value
> written by Wf, as it would not violate happens-before consistency (Rf
> does not happen before Wf, nor is there a write w such that Wf -> w ->
> Rf). However, those same happens-before consistency requirements,
> combined with the happens-before relation from Wv to Rv, guarantee that
> any reads that happen after Rv will not see overwritten writes that
> happen before Wv.
>
> [2] A rather loose argument for sequential consistency is that if there
> were two instances of this class Foo f1 and f2, and thread T1 performed
> { f1.setF(w1); f2.setF(w2); } where another thread T2 performed { int r2
> = f2.getF(); int r1 = f1.getF(); }, it should be impossible for T2 to
> observe w2 but not w1. Why? Because the write of w1 happens before the
> write of w2 (presumably overwriting the value written by some previous
> write w). Therefore, by the "volatile-like" guarantee on f2.f, the
> subsequent read of f1.f cannot see the write w, as w -> write of w1 ->
> write of w2. A better argument would probably construct a sequentially
> consistent equivalent to any schedule, but I haven't tried writing such
> a thing out yet.
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20110202/6ddda3ec/attachment.html>


More information about the Concurrency-interest mailing list