I think you can ensure the ctor has finished even in the face of the unsafest of unsafe sharing, just not with a synchronized block -- you just need to set some sort of barrier. A CountDownLatch would do it, but probably simpler would be a volatile boolean isInitialized. Set that to true as the last action of your constructor, and check that it's true as the first action of every subsequent method. I wonder if this would be an appropriate time for a spin -- while (!isInitialized) {} -- since you expect that in 99.9% of cases you'll loop 0 times, and in that rare case of a safely unpublished reference being reordered relative to the constructor, you might spin once or twice.<div>

<br></div><div>Of course, to do that, you would have to check isInitialized at the start of <i>every</i> method. That implies your class (or at least all its method) has to be final, or subclasses could easily break that invariant.<br>

<div><br><div class="gmail_quote">On Fri, Dec 16, 2011 at 8:52 PM, David Holmes <span dir="ltr"><<a href="mailto:davidcholmes@aapt.net.au">davidcholmes@aapt.net.au</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="im">Zhong Yu writes:<br>
> If the reference is unsafely published, another thread can get the<br>
> reference early; it then calls an instance method which may obtain the<br>
> lock before the creation thread can obtain the lock for the<br>
> constructor. Therefore the other thread can observe the blank state.<br>
> As Ruslan corrected me, no partial state can be observed though.<br>
<br>
</div>The only way this can happen, if you synchronize the whole constructor body,<br>
is if a super class constructor does the unsafe publishing. But in that case<br>
there is no such thing as safe -publishing because the object can escape<br>
before the subclass constructor does any initialization.<br>
<br>
To summarize a long and garbled thread. If the constructor body is<br>
synchronized, there is no accessible state and all methods are synchronized,<br>
then no external user of the class can publish a reference in a way that is<br>
unsafe. If the constructor does the publishing within the synchronized<br>
block, it is still safe. Only if the superclass does it can it possibly be<br>
unsafe.<br>
<br>
Also to address an other point: lock elision is allowed (eg using escape<br>
analysis) but the memory synchronization effects must remain (you can lose<br>
enforced mutual exclusion [as you don't need it], but not happens-before<br>
edges).<br>
<br>
Constructors can't be synchronized simply because back in 1995 no one<br>
realized there could be a need for it. It can be mostly worked around by<br>
using a synchronized block. But you can't synchronize the invocation of the<br>
super constructor.<br>
<br>
End of story :)<br>
<br>
Cheers,<br>
David<br>
<div class="HOEnZb"><div class="h5"><br>
_______________________________________________<br>
Concurrency-interest mailing list<br>
<a href="mailto:Concurrency-interest@cs.oswego.edu">Concurrency-interest@cs.oswego.edu</a><br>
<a href="http://cs.oswego.edu/mailman/listinfo/concurrency-interest" target="_blank">http://cs.oswego.edu/mailman/listinfo/concurrency-interest</a><br>
</div></div></blockquote></div><br></div></div>