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

Vitaly Davidovich vitalyd at gmail.com
Wed Oct 3 11:22:01 EDT 2012


I'm still unclear on whether you have any multi threaded code or not.

To answer your questions:

1) assigning to final list *before* populating it doesn't conform to JMM.
It may work in practice if JIT doesn't rearrange things just because
there's *any* final assignment in the ctor, but it could.  You'd have to
instead populate a temp list and then assign it to the final field.  Again,
this is only important if you're doing data race publishing.

2) final fields get special treatment in JMM - they prevent the reordering
of the final assignment with any prior assignment in program order.
Consider this:

Foo f = new Foo();
In program order, you have assignment in the ctor body followed by normal
assignment to f.  Volatile allows normal stores that *follow* a volatile
store to reorder before it; final doesn't.  Let's decompose the above:
      x = ...
      y = ....
f = <new obj>

If x and/or y are volatile, then f assignment can float above assignments
to x and/or y.  If f is static and read by another thread, it can see
non-null f but not see x and y writes yet.  If x and y are final (or in the
order above, just y can be final), this reordering cannot occur (outside of
bug in JVM).

If you publish f safely, then none of the above makes any difference - the
publication will ensure all writes are visible with the synchronizing

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

> My assumption: I am never getting seeded values from somewhere else.  All
> seed values are passed into the constructor with argument containers.
> My first question is:  why is it ok to assign the final reference to the
> newly created ArrayList before filling it with values?
> Second question is: how is data race for the newly created values in the
> ArrayList solved just by making ArrayList member variable final (rather
> than volatile)?
> So I am getting from you guys that I just have to deep copy the argument
> containers into my own newly created containers, and make the reference to
> the new containers final, AND make sure that no values are ever added to
> the containers after the constructor finishes.  Is this correct?
> Would it be possible to eliminate the deep copy step if my apis required
> that the caller never change the contents of the containers after passing
> them to my constructor?  In that case, maybe I could just assign the
> references to the argument containers to "final volatile" members, and all
> my getters would access thru the final volatile members.
>   ------------------------------
> *From:* Aleksey Shipilev <aleksey.shipilev at oracle.com>
> *To:* Andy Nuss <andrew_nuss at yahoo.com>
> *Cc:* "concurrency-interest at cs.oswego.edu" <
> concurrency-interest at cs.oswego.edu>
> *Sent:* Wednesday, October 3, 2012 7:44 AM
> *Subject:* Re: [concurrency-interest] do constructors ever involve
> threading under the covers?
> Andy,
> On 10/03/2012 06:22 PM, Andy Nuss wrote:
> > So if I follow you correctly, for a constructor that has an array or
> > ArrayList member, creates that array/ArrayList, and fills it with a
> > bunch of seeded values, which are effectively final: another thread will
> > not see the values in the array/ArrayList unless the constructed object
> > is "published" to the other thread, such as with a volatile variable or
> > concurrent map.
> If you are reading those "seeded" values from somewhere else, then there
> is no guarantees you will read the actual values in the constructor
> unless you take the precaution of publishing those values safely. If you
> are populating the list in the constructor with generated values and
> store it in the field, then you are fine:
> public class A {
>     private final List<Integer> list;
>     public A() {
>         list = new ArrayList<>();
>         list.add(1); list.add(2); list.add(3);
>     }
> }
> // everything is visible
> List<Integer> l = new A().list;
> ---------
> private int myRogueField;
> public class B {
>     private final List<Integer> list;
>     public B() {
>         list = new ArrayList<>();
>         list.add(myRogueField);
>     }
> }
> // no guarantees actual $myRogueField value is there
> List<Integer> l = new B().list;
> ---------
> private volatile int myAwesomeField;
> public class C {
>     private final List<Integer> list;
>     public C() {
>         list = new ArrayList<>();
>         list.add(myAwesomeField);
>     }
> }
> // extra care was given when reading $myAwesomeField
> // guaranteed to be visible in the list.
> List<Integer> l = new C().list;
> ---------
> Note that you have to make sure you *read* the correct values when
> passing those to the constructor. Target constructor itself could not
> enforce this.
> > In that case, can someone explain to me how java String, which holds an
> > array of characters, is threadsafe without the need for publishing the
> > string to the other thread?  I.e. even if the array reference is final,
> > the "final" attribute does not apply to the elements of the array.  Same
> > with a final ArrayList reference.
> Sorry, can't see the problem.
> String is immutable, you can not write into the backing char[] array
> there. Once string is created, it copies the contents into its own array
> (modulo contrived cases of subString()) in constructor, gets everything
> freezed as required by JMM, and uses the array then. If you are
> providing the String with safely-acquired source char[] array, it goes
> the "class A" as described above.
> -Aleksey.
> _______________________________________________
> 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/5db4c504/attachment-0001.html>

More information about the Concurrency-interest mailing list