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

Vitaly Davidovich vitalyd at gmail.com
Wed Oct 3 14:58:44 EDT 2012


This depends on what exactly is the scope of a final field assignment, as
Aleksey and I have discussed here.  If the mere presence of a final
assignment in the ctor, irrespective of its order with other local
assignments, means there's a StoreStore barrier placed right before shared
ref assignment, then the whole body of the ctor is visible if the shared
ref is, and thus no such reordering can occur.

If StoreStore is placed right after the final assignment only, then it can.

Sent from my phone
On Oct 3, 2012 2:52 PM, "Zhong Yu" <zhong.j.yu at gmail.com> wrote:

> On Wed, Oct 3, 2012 at 1:44 PM, Vitaly Davidovich <vitalyd at gmail.com>
> wrote:
> > 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.
>
> If the compiler can prove that a write in ctor is to a location that
> cannot be referenced through the final field, then the write can be
> reordered, even after the write to shared ref.
>
> Such proof is probably difficult; unless the field is primitive.
>
> > 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
> >>
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20121003/27b07e6e/attachment-0001.html>


More information about the Concurrency-interest mailing list