[concurrency-interest] do constructors ever involve threading under the covers?

Vitaly Davidovich vitalyd at gmail.com
Wed Oct 3 15:59:37 EDT 2012


The reason is because volatile store allows subsequent (in program order)
normal store to move before it.  The volatile store in your example is the
write of the container to the field, and the normal subsequent store is
assignment of the newly constructed object into the shared ref.  This means
the assignment into shared ref (normal store) can move before volatile
store (the container).  Thus, a reference can be made visible to other
threads before the container is written (I.e. you may see null in the other
thread).

Sent from my phone
On Oct 3, 2012 3:46 PM, "Andy Nuss" <andrew_nuss at yahoo.com> wrote:

> Vitaly,
>
> Can you explain what could go wrong in racy publication within constructor
> if we declared the reference to the member as volatile instead of final?
> For example, we create a temporary reference to the container, and fill
> it.  That's a bunch of stores.  Then we save the temporary container
> reference to a private volatile reference, to "publish" the data to other
> threads that use the class.
>
> Andy
>
>   ------------------------------
> *From:* Vitaly Davidovich <vitalyd at gmail.com>
> *To:* Yuval Shavit <yshavit at akiban.com>
> *Cc:* concurrency-interest at cs.oswego.edu
> *Sent:* Wednesday, October 3, 2012 11:44 AM
> *Subject:* Re: [concurrency-interest] do constructors ever involve
> threading under the covers?
>
> Final is stronger than volatile in terms of store operations inside ctor
> and subsequent assignment to the ref, which happens to enable the racy
> publication that still works; volatile wouldn't work.
> As for your example, it's not allowed.  In order for another thread to
> call verify(), they must have seen a non-null reference.  We also know that
> final assignment prevents reordering of ctor body with assignment to shared
> ref.  I think I agree with Aleksey in that any final assignment in the ctor
> prevents the reordering.  Therefore, if thread sees non-null ref to call
> verify() on, it cannot see a == 0.
> Sent from my phone
> On Oct 3, 2012 1:51 PM, "Yuval Shavit" <yshavit at akiban.com> wrote:
>
> Is that true? I was under the impression that final only has memory
> visibility implications for the final field itself, and anything gotten
> from it. So for instance:
>
> class Foo {
>     int a;
>     final boolean ctorDone;
>
>     Foo() {
>         a = 1;
>         ctorDone = true;
>     }
>
>     void verify() {
>         while (!ctorDone) { /* spin */ }
>         assert a == 1 : a;
>     }
> }
>
> My understanding is that (assuming unsafe publication and all that) the
> JMM is allowed to have a == 0 in Foo.verify, because the memory visibility
> only applies to ctorDone. If ctorDone were a volatile, then reading it
> would ensure a full HB edge, and you'd be guaranteed to see a == 1.
>
> On Wed, Oct 3, 2012 at 1:32 PM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
>
> We may say `final` is stronger than `volatile`, it has all the
> semantics of `volatile', and more.
>
> `volatile` is not strong enough to build thread-safe immutable
> objects, `final` is.
>
> On Wed, Oct 3, 2012 at 8:24 AM, Andy Nuss <andrew_nuss at yahoo.com> wrote:
> > Hi,
> >
> > I have a class with a single member, a reference to a new MessageDigest
> > obtained in the constructor based on the algorithm name passed to the
> > constructor.  The constructor also has a Reader argument and reads all
> the
> > data from the Reader thru an OutputStreamWriter("UTF-8) and passes thru
> to
> > the digest with my own OutputStream filter.  The call to the constructor
> > then accesses the MessageDigest member and calls digest() to get the
> > resulting byte[].  My code by all appearances is single threaded, but I
> am
> > having strange bugs that on one particular machine running vmware, the
> > digest result I am getting (for password hashing) appears not to be
> > repeatable.
> >
> > Basically, I am wondering if another thread can execute the body of the
> > constructor (or in the construction and use of the OutputStreamWriter,
> > within my constructor) that could be causing a bug where memory written
> by
> > the MessageDigest.update() function (triggered within the constructor by
> > writing thru OutputStreamWriter) is not seen in the call to digest() on
> the
> > newly created MessageDigest member after the constructor returns.
> >
> > Andy
> >
> > _______________________________________________
> > 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
>
>
>
> _______________________________________________
> 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
>
>
>
> _______________________________________________
> 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/20121003/6f0e1ee6/attachment-0001.html>


More information about the Concurrency-interest mailing list