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

Stanimir Simeonoff stanimir at riflexo.com
Wed Oct 3 12:48:46 EDT 2012


On Wed, Oct 3, 2012 at 7:28 PM, Andy Nuss <andrew_nuss at yahoo.com> wrote:

> A simple way of asking, if thread (that receives the immutable wrapper)
> runs on a different cpu, then without a memory fence, how does it "see" the
> data?  Do constructors hide a memory fence instruction under the covers?
>

on x86/sparc i.e. TSO, no hardware fence is required only a compilation one
(no reorder of the stores, although the compilers rarely reorder that
anyways). Other than that a store-store fence is required for the final
fields. If the c-tor has no final fields the compiler is free to reorder
the stores as it sees fit.

Stanimir



>   ------------------------------
> *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 9:22 AM
> *Subject:* Re: [concurrency-interest] do constructors ever involve
> threading under the covers?
>
> This does help.
>
> My model is this, and does involve multiple threads.  One thread creates
> and fills container data structure(s) that has no immutable guarantees,
> such as an ArrayList, HashMap, etc.  Then in that same thread, it calls a
> constructor to wrap the container, and give it an immutable api.  Then, the
> hope is that absolutely anyway that any other thread obtains a reference to
> the immutable wrapper, it will "see" all the data in the non-immutable
> containers.  Yes, I hope to not have to make defensive copies!  Yes, the
> same thread that seeded the data into non-thread safe containers is the
> thread that passes those containers to the immutable wrapper.
>
> I understand now that all I have to do is assign my argument containers to
> a final member references in the immutable wrapper.  And that if I do
> defensive copy, do it first, and assign to the final member references at
> the end.
>
> What I don't understand is this: another thread picks up the reference and
> starts using the object.  In all of the above, there was never a volatile
> member involved to ensure that other threads picking up the reference see
> the data in the containers.  Say I do this: new
> SomeThread(immutableReference).start().  This is the beginning of the
> second thread.  What is it about the final references in the immutable
> wrapper that causes SomeThread to "see" that data that Thread A seeded in
> ArrayList/HashMap and then wrapped in immutable wrapper, especially if
> there was no defensive copy?
>
> Once I understand this, then I'll understand the workings of String, which
> clearly have no volatile members.  Strings assume that the thread which
> seeded the char[] is the thread that constructs the String, and somehow
> without any use of volatile, other threads that pick up the reference to
> the constructed String "see" the data in the defensively copyied char[].
> "final" appears to solve reordering problems within the thread, but how
> does it "publish" data?
>
>   ------------------------------
> *From:* Jacy Odin Grannis <jacyg at alumni.rice.edu>
> *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 8:45 AM
> *Subject:* Re: [concurrency-interest] do constructors ever involve
> threading under the covers?
>
> 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
> >
>
>
>
>
>
> _______________________________________________
> 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/5fc94b79/attachment-0001.html>


More information about the Concurrency-interest mailing list