[concurrency-interest] final field/constructor visibility (cf. CyclicBarrier)

thurstonn thurston at nomagicsoftware.com
Sat Sep 27 07:35:23 EDT 2014


I have a question regarding the memory semantics of a constructor that sets
both a final and non-final field.

It was triggered by looking at j.u.c.CyclicBarrier which is defined:

<code>
final int parties
int count

CyclicBarrier(int parties)
   this.parties = parties;
   this.count = parties;
</code>

Now my understanding of the JMM is that any thread referencing the CB is
guaranteed to see  CB#parties as expected, but there is no guarantee that a
thread can't see CB#count = 0 //initialized state, i.e. the fact that the
constructor sets a final variable (#parties) has no bearing at all on any
guarantees of the visibility of #count (and as a side note, the code order
of the writes has no bearing at all either, i.e.

<code>
final int parties
int count

CyclicBarrier(int parties)
    this.count = parties;
    this.parties = parties;
   
</code>

has the same issue.

So the following is theoretically possible
T1                            T2
x = new CB(5)             assert x.getCount() == 5  //may fail

Now CB takes great care that all access of #count is under protection of a
lock (both reads and writes), but there is no happens-before edge between
the constructor writing to non-final #count and T2 (or T3, T4) acquiring the
lock and then reading #count.
In short (although there is a high presumption that the JDK is correct), CB
does not look multi thread-safe (to me).

I was expecting to see:

<code>
CyclicBarrier(int parties)
    this.lock.lock();
    this.count = parties;
    this.lock.unlock();
    this.parties = parties;
   
</code>
or something similar (of course the lock#lock() would be uncontended and so
shouldn't present any substantial performance cost); this would provide the
necessary happens-before edge (release of lock happens-before any subsequent
acquisition of said lock).


As a side note, this is not the situation that generally causes confusion
with respect to final field visibility guarantees, e.g. where a constructor
writes a final Map field and then populates the Map (I think that's been
settled?)

Someone want to set me straight?






--
View this message in context: http://jsr166-concurrency.10961.n7.nabble.com/final-field-constructor-visibility-cf-CyclicBarrier-tp11306.html
Sent from the JSR166 Concurrency mailing list archive at Nabble.com.


More information about the Concurrency-interest mailing list