From: markspace on 19 Jul 2010 19:03 Peter Duniho wrote: > If what you say were true, then you could not even count on the Runnable > instance that you created to be valid during the invoked execution, > since that's something that happened before the call to invokeLater(), > but which wasn't synchronized. The "temp" field itself would be safe, Correct. The Runnable here is not inherently thread safe, hence the need for the volatile keyword. > but nothing else in the Runnable instance would be (including, for > example, a v-table as might be used to dispatch the call to run()). There's nothing in the JLS that describes a need to make *methods* safe for concurrency, or for the programmer to worry about internal structures such as a hypothetical v-table. The JVM is guaranteed to construct a class correctly. The fields used by the programmer must be made thread safe somehow by the programmer. Right now you are just makin' stuff up. Weird side note: I was just reading through the JLS to make sure I had a couple of things right. You know what else is guaranteed to be visible and thread safe? Objects referred to by final fields, up to the point where said objects are assigned to the final field. Thus this works as good as a volatile: public class Main { public static void main( String... args ) { final MyClass test = new MyClass(); SwingUtilities.invokeLater( new Runnable() { private final MyClass model = test; public void run() { ... // ok to use model now... } } ); } }
From: Peter Duniho on 19 Jul 2010 19:17 markspace wrote: > Peter Duniho wrote: > >> If what you say were true, then you could not even count on the >> Runnable instance that you created to be valid during the invoked >> execution, since that's something that happened before the call to >> invokeLater(), but which wasn't synchronized. The "temp" field itself >> would be safe, > > Correct. The Runnable here is not inherently thread safe, hence the > need for the volatile keyword. It is quite common to pass a Runnable to invoke�() without any use of "volatile" or other synchronization in the implementation. None of those examples would be correct if your assertion was. >> but nothing else in the Runnable instance would be (including, for >> example, a v-table as might be used to dispatch the call to run()). > > There's nothing in the JLS that describes a need to make *methods* safe > for concurrency, or for the programmer to worry about internal > structures such as a hypothetical v-table. The JVM is guaranteed to > construct a class correctly. The fields used by the programmer must be > made thread safe somehow by the programmer. > > Right now you are just makin' stuff up. I'm simply pointing out that there are implicit order-of-operation guarantees that necessarily come along with something like the invoke�() methods that, without such guarantees, would break all sorts of code, including that implicitly executed. I'm only "makin' stuff up" inasmuch as I haven't bothered to read the JLS for the purpose of this discussion. But I don't need to. It's patently obvious that the invoke�() methods couldn't possibly be useful unless they included synchronization between the thread that calls them and the thread where the Runnable is actually invoked. The only way to safely get the Runnable reference from one thread to the other is for there to be some synchronization, and such synchronization will necessarily take care of ensuring everything up to the invoke�() call is seen in the other thread after the invoke�() call. I did mention other aspects of initialization in my discussion, but you seem to be getting too distracted by the specifics of those comments, and I now regret introducing those comments. I should have simply omitted them, because they aren't really needed in order to understand why invoke�() must have synchronization. The EDT can't even reliably get the reference to the invoked Runnable unless there's some synchronization. Pete
From: John B. Matthews on 19 Jul 2010 21:30 In article <i22ll3$hdt$1(a)news.eternal-september.org>, markspace <nospam(a)nowhere.com> wrote: > Weird side note: I was just reading through the JLS to make sure I > had a couple of things right. You know what else is guaranteed to be > visible and thread safe? Objects referred to by final fields, up to > the point where said objects are assigned to the final field. Thus > this works as good as a volatile: > > public class Main { > public static void main( String... args ) { > final MyClass test = new MyClass(); > SwingUtilities.invokeLater( new Runnable() { > private final MyClass model = test; > public void run() { > ... // ok to use model now... > } > } ); > } > } IIUC, this is foundational to the lazy initialization holder class idiom [1], also known as the initialize-on-demand holder class idiom [2]. [1] Joshua Bloch, Effective Java, second edition, item 71. [2]<http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom> -- John B. Matthews trashgod at gmail dot com <http://sites.google.com/site/drjohnbmatthews>
From: Lew on 19 Jul 2010 21:40 markspace wrote: >> Weird side note: I was just reading through the JLS to make sure I >> had a couple of things right. You know what else is guaranteed to be >> visible and thread safe? Objects referred to by final fields, up to >> the point where said objects are assigned to the final field. Thus >> this works as good as a volatile: >> >> public class Main { >> public static void main( String... args ) { >> final MyClass test = new MyClass(); >> SwingUtilities.invokeLater( new Runnable() { >> private final MyClass model = test; >> public void run() { >> ... // ok to use model now... Or you could use 'test' directly. >> } >> } ); >> } >> } John B. Matthews wrote: > IIUC, this is foundational to the lazy initialization holder > class idiom [1], also known as the initialize-on-demand holder class > idiom [2]. > > [1] Joshua Bloch, Effective Java, second edition, item 71. > [2]<http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom> Actually what's foundational to that is not so much final variables as final static fields. -- Lew
From: Arne Vajhøj on 19 Jul 2010 22:12
On 19-07-2010 14:51, Peter Duniho wrote: > The first mechanism has to do with semantics surrounding object > construction. In .NET, the specification ensures that whatever happens > in the constructor "happens before" any other code that uses the > reference after the constructor completes (.NET doesn't actually use the > term "happens-before", but it's the same idea). I would expect Java to > be the same in this respect. Where does it say that? The only thing I can find seems to say the exact opposite: <quote> It is explicitly not a requirement that a conforming implementation of the CLI guarantee that all state updates performed within a constructor be uniformly visible before the constructor completes. </quote> Arne |