[concurrency-interest] synchronized constructors

Kearney, Joe Joe.Kearney at gsacapital.com
Fri Dec 16 05:45:11 EST 2011

Of course, and I would never argue with Mr Turing. I meant this only in the simple case where it's easy to deduce that no other thread sees the monitor, in such cases where the JVM can prove it.

-----Original Message-----
From: Roland Kuhn [mailto:rk at rkuhn.info] 
Sent: 16 December 2011 10:35
To: Kearney, Joe
Cc: Zhong Yu; concurrency-interest
Subject: Re: [concurrency-interest] synchronized constructors

On Dec 16, 2011, at 10:59 , Kearney, Joe wrote:

> How much of that locking is allowed to be elided away?
> If you call synchronized(this) {} in a constructor, I would argue that

> provably no other thread can acquire the lock yet

This is not true: the constructor might write "this" to a static volatile field, thereby correctly publishing it to another thread, which might want to acquire the same lock and would have to block. And since the JVM is Turing complete, it is impossible to prove in the general case that this cannot happen (there may be very specific constructors which allow this, though, and you could argue that all of the IDE auto-generated ones fall into this category).

> . So can the locking be compiled away, even though the induced fence would need to stay?
> -----Original Message-----
> From: concurrency-interest-bounces at cs.oswego.edu 
> [mailto:concurrency-interest-bounces at cs.oswego.edu] On Behalf Of 
> Roland Kuhn
> Sent: 16 December 2011 09:49
> To: Zhong Yu
> Cc: concurrency-interest
> Subject: Re: [concurrency-interest] synchronized constructors
> As I was recently made aware: the rules for write reordering are not as weak as you think.
> http://java.sun.com/docs/books/jvms/second_edition/html/Threads.doc.ht
> ml#24432
> Section 8.8 of the JVM spec requires that a write cannot be moved earlier across a "lock" operation. This means that a synchronized {} in the constructor solves the issue.
> Regards,
> Roland
> On Dec 16, 2011, at 08:58 , Zhong Yu wrote:
>> I'm totally sympathetic to this design goal - if an object claims to 
>> be thread safe, it should survive unsafe publication without problems.
>> I believe all java.util.concurrent classes have this property.
>> However, `synchronized` constructor cannot help to reach that goal.
>>   foo = new Foo();
>> is roughly equivalent to
>>   [A]    tmp = allocate memory space for sizeof(Foo)
>>   [B]    zero the space. (this may occur before [A])
>>   [1]    tmp.Foo(); // as if the constructor is an instance method
>>   [2]    foo = tmp;
>> [2] can be reordered before [1], so other threads may observe 
>> blank/partial state through `foo` reference. This reordering is 
>> allowed even if `Foo()` is synchronized.
>> This problem affects some "thread safe" classes like java.util.Vector.
>> If a Vector object is unsafely published, program can crash 
>> unexpectedly. I bet that's a huge surprise to most Java programmers.
>> But I don't think the "unenlightened mass" are to blame. We have this 
>> strong intuition that an object comes to existence only after 
>> construction. Nobody outside of construction should observe a 
>> partially constructed object (unless `this` is leaked during 
>> construction).
>> If JMM has this simple "whole-birth" guarantee, many man-hours of 
>> anguish will be saved. You can innocently do a double checked 
>> locking, and nobody is going to yell at your naivety.
>> Unfortunately JMM doesn't have this guarantee. Allegedly such 
>> guarantee carries a performance penalty. The only work around is 
>> through `final` fields. Neither `synchronized` nor `volatile` is 
>> useful for this purpose (many people are mistaken on this point; it 
>> is due to their whole-birth intuition, subconsciously adding a 
>> synchronization order from end of constructor to begin of instance
>> methods)
>> We are encouraged to use `final` fields whenever we can. One crucial 
>> reason is for the memory effect guarantee. However, using `final` 
>> fields will incur the same performance penalty of whole-birth 
>> guarantee. We have a great contradiction here. Either `final` is not 
>> cheap, so we should avoid `final` fields if we can; or `final` is 
>> cheap, so whole-birth guarantee can be established cheaply, yielding 
>> `final` unnecessary.
>> JMM does guarantee that [2] cannot be reordered before [B], otherwise 
>> other threads can observe garbage state. Let's call this the "blank"
>> guarantee. It's also a mystery to me why whole-birth guarantee can be 
>> fundamentally more expensive than blank guarantee.
>> Note that not everybody promotes the use of `final` though. We can 
>> sense how reserved David Holmes is through his words: " #Sometime# a 
>> class needs to add #some# protection against unsafe-publication that 
>> might violate #important# semantic guarantees of the object"
>> (We had a similar discussion in a September thread titled 
>> "Interesting anti-pattern with volatile"; however I cannot find it on 
>> the mailing list archive, so no link.)
>> Zhong Yu
>> P.S. a "fix" to Vector's vulnerability to unsafe publication
>> class Vector
>>   final Params ctorParams;
>>   Vector(params)
>>       ctorParams = new Params(params);
>>   boolean initDone;
>>   void ensureInit()
>>       if(!initDone)
>>           initialize this with ctorParams ...
>>           initDone = true;
>>   synchronized
>>   public Foo anyOtherMethod(Bar)
>>       ensureInit();
>>       actual work...
>> Of course, this solution sucks. The role of constructor is severely weakened.
>> _______________________________________________
>> Concurrency-interest mailing list
>> Concurrency-interest at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> --
> [scala-debate on 2009/10/2]
> Viktor Klang: When will the days of numerical overflow be gone?
> Ricky Clarkson: One second after 03:14:07 UTC on Tuesday, 19 January 
> 2038
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

Simplicity and elegance are unpopular because they require hard work and discipline to achieve and education to be appreciated.
  -- Dijkstra

More information about the Concurrency-interest mailing list