[concurrency-interest] synchronized constructors

Boehm, Hans hans.boehm at hp.com
Fri Dec 16 20:01:36 EST 2011


Interesting question, though I'm not sure I understand the problem correctly.  It seems to me that synchronized(this) in the constructor, and a synchronized second initialization phase ensure that all clients see either one of

1) the zero initialized object
2) the fully constructed object, pre-phase-2 initialization object, or
3) the fully initialized object

I don't see any way to prevent untrusted code running in multiple other threads from getting a hold of a reference to the object without establishing a happens-before relationship to ensure that it sees the object fully initialized.  Thus to be fully safe, I suspect other methods have to be prepared to find an object in any of those states.  Presumably they could explicitly check which one applies.  That doesn't seem like an entirely satisfactory answer, but ...

Hans

From: Roland Kuhn [mailto:rk at rkuhn.info]
Sent: Friday, December 16, 2011 2:53 PM
To: Boehm, Hans
Cc: Yuval Shavit; Zhong Yu; concurrency-interest at cs.oswego.edu
Subject: Re: [concurrency-interest] synchronized constructors

This sounds like it is impossible to construct a mutable object in a way so that it is immune against improper publication. If the aforementioned is wrong-which I hope-then would you please tell me what the cheapest way is of achieving this goal? One thing I could think of is just putting all non-final fields in another class and have a reference to that be held in a final field; if this works, it would be quite expensive, so any better solution would be welcome.

You might ask, why have a non-final field without proper synchronization, so let me add that the background to this question is that in my case the construction of the object needs to proceed in two phases because of other inter-dependencies, which requires certain fields to be written to after the constructor has finished; they will be written to only exactly once, and this happens before "untrusted" client code obtains the reference (in program order).

Thanks in advance,

Roland

On Dec 16, 2011, at 22:49 , Boehm, Hans wrote:


Just to be clear: Safe publication for final fields requires that you do not make a pointer to the object available to other threads (publish it) before the constructor finishes.  "Safe publication" as used below is a slightly stronger property; you also should not communicate the pointer post-construction to another thread via a data race.  Avoiding them both is great advice, but the second one may be difficult to avoid if you need to give a reference to your object to code you don't trust.  Malicious code could always pass the object to a third thread through a race, hoping that the third thread, which has no happens-before relationship to the other two, would find your object in an inconsistent state.  My intuition is that this is a rare case, but one that does occur.  When it does occur, the odds of an actual security hole are probably small, but so are the odds of proving security properties without addressing the issue.

Hans

From: concurrency-interest-bounces at cs.oswego.edu<mailto:concurrency-interest-bounces at cs.oswego.edu> [mailto:concurrency-interest-bounces at cs.oswego.edu] On Behalf Of Yuval Shavit
Sent: Friday, December 16, 2011 11:59 AM
To: Zhong Yu
Cc: concurrency-interest at cs.oswego.edu<mailto:concurrency-interest at cs.oswego.edu>
Subject: Re: [concurrency-interest] synchronized constructors

On Fri, Dec 16, 2011 at 2:10 PM, Zhong Yu <zhong.j.yu at gmail.com<mailto:zhong.j.yu at gmail.com>> wrote:
On Fri, Dec 16, 2011 at 8:38 AM, Yuval Shavit <yshavit at akiban.com<mailto:yshavit at akiban.com>> wrote:
> Several people have made the claim that you could see partially initialized
> state even if the constructor were synchronized, and I don't see how this
> could be. Yes, you could assign MyPoint myUnsafeRef before MyPoint()
> finishes -- but if you ever tried to *use* myUnsafeRef, you would run into a
> synchronized block which would then ensure that the constructor
> happened-before whatever method you're writing. Seems to me you should see
> the fully-thread-safe, not-partially-initialized object at that point.
If the reference is unsafely published, another thread can get the
reference early; it then calls an instance method which may obtain the
lock before the creation thread can obtain the lock for the
constructor. Therefore the other thread can observe the blank state.
As Ruslan corrected me, no partial state can be observed though.

Ah yes, I hadn't thought of that.

So now, in order to have my class be over-achievingly thread safe, I need to replace my synchronized methods with a latch that waits for construction to finish and *then* a synchronized (this) {...}. But I probably decide that this is really going far out of my way to support a bad usage pattern, so I throw up my arms and say "you'll see either totally blank or post-initialization state, but not partial initialization."  But that means I have to guard against uninitialized state in each method, so I probably throw up my arms again and say "just publish the darn object safely!"  And then the JLS people come to me and say, "well if that's your requirement, why do you want a synchronized constructor?"  And suddenly the whole thing makes sense.

This has been an interesting discussion for me! Thanks everyone. :)

-Yuval
_______________________________________________
Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu<mailto: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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20111217/3f5d49c6/attachment.html>


More information about the Concurrency-interest mailing list