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

Vitaly Davidovich vitalyd at gmail.com
Wed Oct 3 11:24:40 EDT 2012


Oops, I miswrote #2 - final fields prevent *subsequent* reordering, not
prior.

Sent from my phone
On Oct 3, 2012 11:22 AM, "Vitaly Davidovich" <vitalyd at gmail.com> wrote:

> Andy,
>
> 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:
> ctor:
>       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
> reader.
>
> 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/af0f045a/attachment.html>


More information about the Concurrency-interest mailing list