[concurrency-interest] synchronized constructors

Yuval Shavit yshavit at akiban.com
Sat Dec 17 21:14:56 EST 2011


That's what I would have thought too, by reading the standard "if a field
is ever guarded by a given monitor, it should always be" advice. But in
this case, I would think roach motel semantics would give you some
benefits. Wouldn't it mean that the write to the reference would have to
happen after the empty synchronized block (and thus after the interesting
bits of the constructor), and that there'd be a happens-before relative to
any subsequent synchronized methods?

On Sat, Dec 17, 2011 at 6:40 PM, David Holmes <davidcholmes at aapt.net.au>wrote:

> Roland,
>
> An empty synchronized block in a constructor, when there are no other
> synchronized regions of code, gains you nothing under the JMM as there are
> no happens-before edges established. Are you
> relying on the implementation of synchronized to issue specific memory
> barriers here?
>
> David
>
> > -----Original Message-----
> > From: Roland Kuhn [mailto:rk at rkuhn.info]
> > Sent: Sunday, 18 December 2011 1:46 AM
> > To: dholmes at ieee.org
> > Cc: Zhong Yu; concurrency-interest at cs.oswego.edu
> > Subject: Re: [concurrency-interest] synchronized constructors
> >
> >
> > Thank you, David and Hans, for clarifying these semantics. The
> > OP’s question has been answered, and I think I can also derive an
> > answer for my question. I’ll try to wrap it up below, please
> > correct or confirm:
> >
> > class IAmSafe {
> >   private volatile int x;
> >   IAmSafe() {
> >     x = 5;
> >     synchronized(this) {}
> >   }
> >   public int getX() {
> >     return x;
> >   }
> > }
> >
> > Assuming that the java.lang.Object constructor is well-behaved,
> > it should be impossible under any circumstances (barring
> > reflective modification) that a call to getX() returns anything
> > but 5, right?
> >
> > If this is true, then the cheapest solution to my multi-stage
> > construction problem—where I completely control the program flow
> > up to the point where I consider the object initialization
> > finished—on x86 processors looks like this:
> >
> > class ComplexDeps {
> >   final int someValue;
> >   ComplexDeps(int someValue) {
> >     this.someValue = someValue;
> >   }
> >   // stage 2
> >   private volatile OtherThing thing;
> >   public void init(OtherThing thing) {
> >     this.thing = thing;
> >     synchronized {}
> >   }
> >   // other stuff which reads someValue & “thing”, never writes to
> > “thing” and runs only after init() in program order
> > }
> >
> > IIUC, there will be a (half-way) expensive fence-like instruction
> > emitted at the end of init(), but apart from that all read
> > accesses after construction should be cheap. Any nobody will ever
> > see “thing” uninitialized.
> >
> > Regards,
> >
> > Roland
> >
> > On Dec 17, 2011, at 09:57 , David Holmes wrote:
> >
> > > Correction ...
> > > I wrote:
> > >> Zhong Yu writes:
> > >>> Suppose constructor java.util.Vector() is synchronized
> > >>>
> > >>>    static Vector v;
> > >>>
> > >>>    // thread 1
> > >>>    v = new Vector();
> > >>>
> > >>>    // thread 2
> > >>>    Vector r = v;
> > >>>    if(r!=null)
> > >>>      r.add(x);
> > >>>
> > >>> The last line can throw exception, because thread 2 can observe the
> > >>> blank state of the object
> > >>
> > >> No it can not.
> > >> Completion of the constructor happens-before the reference is
> > published.
> > >
> > > Delete this sentence. It's wrong but not relevant to the argument.
> > >
> > > David
> > > -----
> > >
> > >
> > >> The acquiring of the monitor in add() can only happen when the
> > >> monitor is released by the constructor. The release of the
> > >> monitor in thread
> > >> 1 happens-before the acquire of the monitor by thread 2. All the
> > >> constructor
> > >> actions happen-before the release of the monitor.
> > >>
> > >> The publishing of the Vector can not be moved prior to the
> > acquisition of
> > >> the monitor in the constructor ("roach motel semantics").
> > >>
> > >> David
> > >> -----
> > >>
> > >>
> > >>> , yet Vector.add() presumes a> post-construction state.
> > >>
> > >>> Zhong Yu
> > >>>
> > >>> On Fri, Dec 16, 2011 at 7:52 PM, David Holmes
> > >>> <davidcholmes at aapt.net.au> wrote:
> > >>>> Zhong Yu writes:
> > >>>>> 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.
> > >>>>
> > >>>> The only way this can happen, if you synchronize the whole
> > >>> constructor body,
> > >>>> is if a super class constructor does the unsafe publishing. But
> > >>> in that case
> > >>>> there is no such thing as safe-publishing because the object
> > >> can escape
> > >>>> before the subclass constructor does any initialization.
> > >>>>
> > >>>> To summarize a long and garbled thread. If the constructor body is
> > >>>> synchronized, there is no accessible state and all methods are
> > >>> synchronized,
> > >>>> then no external user of the class can publish a reference in a
> > >>> way that is
> > >>>> unsafe. If the constructor does the publishing within the
> > synchronized
> > >>>> block, it is still safe. Only if the superclass does it can it
> > >>> possibly be
> > >>>> unsafe.
> > >>>>
> > >>>> Also to address an other point: lock elision is allowed (eg
> > >> using escape
> > >>>> analysis) but the memory synchronization effects must remain
> > >>> (you can lose
> > >>>> enforced mutual exclusion [as you don't need it], but not
> > >> happens-before
> > >>>> edges).
> > >>>>
> > >>>> Constructors can't be synchronized simply because back in 1995 no
> one
> > >>>> realized there could be a need for it. It can be mostly
> > >> worked around by
> > >>>> using a synchronized block. But you can't synchronize the
> > >>> invocation of the
> > >>>> super constructor.
> > >>>>
> > >>>> End of story :)
> > >>>>
> > >>>> Cheers,
> > >>>> David
> > >>>>
> > >>>
> > >>
> > >> _______________________________________________
> > >> Concurrency-interest mailing list
> > >> Concurrency-interest at cs.oswego.edu
> > >> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> > >>
> > >
> > > _______________________________________________
> > > 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
> >
> >
>
>
> _______________________________________________
> 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/20111217/b32d7980/attachment.html>


More information about the Concurrency-interest mailing list