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

Jacy Odin Grannis jacyg at alumni.rice.edu
Wed Oct 3 11:45:46 EDT 2012


I think there are two streams of thought here that are getting crossed.

First, I agree with Vitaly that it's still unclear if you have
multi-threading going on at all.  In the example you provide, is the
EffectivelyImmutableArrayListWrapper used across multiple threads?  If
it's not, than there's no need for really any modifier.  For a single
thread, you never have to worry about reordering.  It might likely
happen, but you are guaranteed that, going by program order,
operations which happen 'before' will be done prior to their use.  So
if the Wrapper is constructed and used within a single thread, you
don't need volatile, or final, or even to create a copy at all if the
'list' arg is never going to be modified subsequent to wrapping.

Second, based on the snipped below, if you *do* have multiple threads,
which surely you must?  then the areas for concern would be how the
'list' arg is passed in (i.e., is it getting populated in another
thread?) and then how the Wrapper is used after construction.  So
let's address those:

the list arg that you are passing in:  if it comes from the same
thread, you're in the single thread situation and
concurrency/reordering isn't an issue *up to the point of calling the
constructor*.  However, if you are populating the list in a different
thread before passing in, you need to make sure you pass/populate the
list in a thread safe fashion.  Otherwise, writes from the populating
thread might not have been done in the list when the Wrapper
constructing thread does its thing.

use of the wrapper:  if the wrapper will be used in the same thread it
was constructed in, then you're in the single thread scenario.  If it
will be used by multiple threads, then you have to worry about how you
construct it.  If the list arg you are passing in is not referenced by
any other threads and isn't going to be updated anywhere else, you
don't need to create a deep copy.  You can simply assign it to a final
variable, and you are good to go.  String(char[]) creates a defensive
copy to *guarantee* that the contents won't change (it doesn't trust
that you'll behave and drop your reference to the char[] you pass in).
 But creating a defensive copy is only necessary if you don't have
control over who might invoke the constructor.  If you are going to
create a defensive copy, your best bet would be to create the copy,
then assign the fully populated copy to a final variable.  Assigning
an empty copy to a volatile variable and then populating it doesn't
work.  The volatile only applies to that reference, not to the
references maintained inside the list itself.  You could create a
fully populated copy and then assign to a volatile variable, but if
you don't plan to change that reference, final would be a much better
option.

Does that help?

jacy


On Wed, Oct 3, 2012 at 9:37 AM, Andy Nuss <andrew_nuss at yahoo.com> wrote:
> For clarification, lets say a caller passes my constructor an ArrayList with
> seeded values.
>
> class EffectivelyImmutableArrayListWrapper {
>     private volatile ArrayList  mylist;
>     EffectivelyImmutableArrayListWrapper (ArrayList list)
>     {
>           // .... create mylist and copy all values from list into mylist
>           // this class only provides getters for mylist
>           // mylist never changes except in this constructor where created
> and filled
>     }
>
>     // getter functions for mylist
> }
>
> From the above snippet, we see that we are attempting to provide a
> publishing wrapper/snapshot for an ArrayList.  Is "volatile" necessary here?
> I assume that "final" does not work, because "mylist" is just a reference.
> Also, what if the contract of the constructor was that the caller would
> never change/use the arraylist arg after calling the constructor: in that
> case, could the constructor just copy the arg reference to the volatile
> "mylist" member and be done?
>
> Assuming that I am correct that "mylist" has to be volatile, how does
> java.lang.String accomplish immutability of the private char[] without
> making it volatile?
>
> ________________________________
> From: Andy Nuss <andrew_nuss at yahoo.com>
> To: "concurrency-interest at cs.oswego.edu"
> <concurrency-interest at cs.oswego.edu>
> Sent: Wednesday, October 3, 2012 7:22 AM
>
> Subject: Re: [concurrency-interest] do constructors ever involve threading
> under the covers?
>
> (It was a reply accident that I did not reply to list.)
>
> 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.
>
> 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.
>
> ________________________________
> From: Aleksey Shipilev <aleksey.shipilev at oracle.com>
> To: Andy Nuss <andrew_nuss at yahoo.com>
> Sent: Wednesday, October 3, 2012 7:11 AM
> Subject: Re: [concurrency-interest] do constructors ever involve threading
> under the covers?
>
> Any specific reason you are not replying to the list? :)
>
> On 10/03/2012 06:04 PM, Andy Nuss wrote:
>> The reason I ask about the constructor is this: java memory model
>> provides a guarantee that all memory set/changed in the constructor is
>> immediately visible to any other thread (that receives a reference to
>> new object) after the constructor returns.  Is this true?
>
> Ughm, there is a requirement for the final field values of newly
> constructed objects set in constructor are visible after constructor
> finishes, and only in the case if you haven't leaked the reference to
> "this" in the constructor.
>
> There is no memory semantics for constructor invocation otherwise. I.e.:
>
> class A {
>   private int myField;
>
>   public int get() {
>       // DOES NOT force $myField visibility
>       return new A(myField).value;
>   }
> }
>
> class B {
>   int v;
>   public B(int v) { value = v; }
> }
>
> Neither it would change if you make B.v final.
>
>> Is the contructor always executed in the same thread as its caller?
>
> Yes, it acts like ordinary method in this regard, no specific treatment.
>
> -Aleksey.
>
>
>
>
>
>
>
> _______________________________________________
> 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