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

Zhong Yu zhong.j.yu at gmail.com
Wed Oct 3 16:40:08 EDT 2012


It would be more intuitive to define the freeze action the same as the
write to the final field. I guess the authors wanted to be able to
freely reorder intra-constructor actions, regardless of final fields,
so freeze is postponed.

In this example

    ctor()
    {
        f = v; // final
        leaked = this;
    }

when another thread sees a non null `leaked`, it's not guaranteed to
see `leaked.f==v`, because of the possible reordering.

On Wed, Oct 3, 2012 at 3:10 PM, Vitaly Davidovich <vitalyd at gmail.com> wrote:
> I think Yuval and you are right.  I just looked at the JLS and example
> 17.5-1 shows that the StoreStore barrier doesn't extend to end of
> constructor automatically.  I guess the ThreeStooges.java example that
> Aleksey linked to earlier works, despite the final assignment occurring
> before the writes into the list, is because those writes are reachable via
> the final field and thus get included in the freeze action.
>
> Sent from my phone
>
> On Oct 3, 2012 3:32 PM, "Zhong Yu" <zhong.j.yu at gmail.com> wrote:
>>
>> We may say a final field `f` protects an extended territory, anything
>> reachable from `f` is in the territory. Any write (before constructor
>> exit) into the territory cannot be reordered with publication of
>> `this`. Other writes are not protected by this treaty. In Yuval's
>> example, `a=1` can be reordered to an arbitrarily late place.
>>
>> On Wed, Oct 3, 2012 at 2:14 PM, Vitaly Davidovich <vitalyd at gmail.com>
>> wrote:
>> > Right, but that's a different matter since final assignment is
>> > specifically
>> > the order between the final assignment in ctor and ref assignment rather
>> > than other surrounding operations.
>> >
>> > Sent from my phone
>> >
>> > On Oct 3, 2012 3:09 PM, "Zhong Yu" <zhong.j.yu at gmail.com> wrote:
>> >>
>> >> I guess the spec is deliberately weakened, so that for example
>> >>
>> >>     anInt = 1;
>> >>     anStr = new String(bytes);
>> >>
>> >> no ordering constraint is imposed; the 1st write can be reordered
>> >> after the 2nd, passing the constructor with final field writes.
>> >>
>> >> This seems unnecessarily sophisticated; too much for mortals.
>> >>
>> >> On Wed, Oct 3, 2012 at 1:58 PM, Vitaly Davidovich <vitalyd at gmail.com>
>> >> wrote:
>> >> > 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
>> >> >> >>
>> >> >> >


More information about the Concurrency-interest mailing list