From: markspace on 19 Jul 2010 13:43 www wrote: > This is equal to running my program in single thread. Am I correct? Not really, no. The synchronized keyword provides different semantics than just "single threaded behavior," whatever that might mean. > More specifically, how can I make sure that checkSomething() is finished > at the top of doThis()? Using synchronized as shown will do that. This is called MUTEX ("mutual exclusion") and is one of the semantics "synchronized" provides, but not the only one. Hint: Google MUTEX.
From: Lew on 19 Jul 2010 13:49 Jim Janney wrote: >> The simplest and least error prone approach is to declare both methods >> as synchronized, e.g. > >> synchronized public void doThis() > >> synchronized public void checkSomething() > www wrote: > This is equal to running my program in single thread. Am I correct? > What do you mean by "equal"? It's not the same as running in a single thread, no, and nor is it always going to be enough for every concurrent situation. Whether it's as safe as running in a single thread depends on the details of the situation, but for this simple situation it seems to be. Pete alluded to risks with this approach upthread. > More specifically, how can I make sure that checkSomething() is finished > at the top of doThis()? > With the simple approach shown, you can be sure that 'checkSomething()' and 'doThis()' are not executing simultaneously within the same instance. You need to learn to think in terms of concurrent programming, which takes a bit of time. One trick is to think in terms of "critical sections". Those are parts of code that access the same data, so in a concurrent environment they can interfere with each other unless you're careful. To be careful, you apply 'synchronized' or 'volatile' or a raft of other techniques. A critical section is a shortest piece of code that operates on the shared data as a unitary operation. The collection of critical sections is the collection of pieces of code that have to honor the same synchronization mechanism. By the way, this is for read or write. You cannot synchronize on, say, just the write sections and expect unsynchronize read sections to work correctly. Another trick is to master the Java concept of /happens-before/. This is the set of rules about what changes threads can see that were made by other threads. It's a good trick because once you get the concept, you can reason about whether changes will be visible or conflict between threads. -- Lew
From: markspace on 19 Jul 2010 14:13 www wrote: > The code below is completely fine if running on single-thread > environment. But it could break if running on multi-thread environment. > public class MyClass > { > private Person tim = new Person("Tim"); > private Person tom = new Person("Tom"); > Here's a weird question for this list at large. Are the above lines even thread safe? Objects are guaranteed to be correctly constructed, but these objects might be mutable. And the fields tim and tom are not final, so they aren't guaranteed to be published correctly either. So one thread has to construct this "MyClass" and then some other thread might consume it (note that the methods of MyClass are not static, so an instance does have to be constructed): public class Main { public static void main( String... args ) { MyClass test = new MyClass(); ... // now what? } } So here if one then passed the "test" object to, for example, the EDT for use in a GUI, one still needs synchronization/happens-before to make the "test" object correctly visible to the EDT, or any other thread besides main, yes? I could look this up but I'm feeling a bit lazy right now, and I thought the OP could use some discussion of other thread-safe semantics besides mutex, which is the only one he seems to understand right now.
From: Jim Janney on 19 Jul 2010 14:40 www <www(a)nospam.com> writes: > Jim Janney wrote: > >> >> The simplest and least error prone approach is to declare both methods >> as synchronized, e.g. >> >> synchronized public void doThis() >> >> synchronized public void checkSomething() >> > > This is equal to running my program in single thread. Am I correct? > > More specifically, how can I make sure that checkSomething() is > finished at the top of doThis()? Assume that there is an instance of MyClass and that some thread is executing in either doThis() or checkSomething() on that instance. The synchronized declaration accomplishes two things: 1) If any other thread tries to execute doThis() or checkSomething() on the same instance, it will block until the first thread exits the synchronized method it's in, either by returning normally or by throwing an exception. 2) By the time the blocked thread is allowed to enter, any changes to the object made by the previous thread will be visible in memory to the second thread. In other words, it guarantees both exclusion and memory consistency. -- Jim Janney
From: Peter Duniho on 19 Jul 2010 14:51
markspace wrote: > www wrote: >> The code below is completely fine if running on single-thread >> environment. But it could break if running on multi-thread environment. > >> public class MyClass >> { >> private Person tim = new Person("Tim"); >> private Person tom = new Person("Tom"); >> > > > Here's a weird question for this list at large. Are the above lines > even thread safe? Objects are guaranteed to be correctly constructed, > but these objects might be mutable. And the fields tim and tom are not > final, so they aren't guaranteed to be published correctly either. > > So one thread has to construct this "MyClass" and then some other thread > might consume it (note that the methods of MyClass are not static, so an > instance does have to be constructed): > > public class Main { > public static void main( String... args ) { > MyClass test = new MyClass(); > ... // now what? > } > } > > So here if one then passed the "test" object to, for example, the EDT > for use in a GUI, one still needs synchronization/happens-before to make > the "test" object correctly visible to the EDT, or any other thread > besides main, yes? For the EDT example, there are actually two different mechanisms that should ensure thread safety. One of them, I would have to look up to make sure is supported in the JVM (but I'm pretty sure it is). The other is inherent in your statement "passed the 'test' object to�the EDT". 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. Note that this is a good reason for not letting the "this" reference leak out of the constructor, because doing so would circumvent whatever assurances the object construction semantics would normally provide. The second mechanism has to do with how object references get from one thread to another. In particular, keep in mind that "happens before"/"happens after" has a sort of transitive nature to it. Everything that happens before something synchronized in one thread is visible to everything that happens after the inspection of that synchronized something in a different thread. In the case of the EDT, the typical way an object reference would get from another thread to the EDT is via the invokeLater() or invokeAndWait() methods. These methods are inherently synchronized themselves; it's a natural consequence of what must happen for the data passed to the methods to get to the EDT. This means that everything that happened in that other thread before the call to invokeLater() or invokeAndWait() is necessarily going to be visible to the EDT, as long as it only inspects that data as a result of whatever Runnable was passed to the invoke�() method. Likewise if the data was passed not via an invoke�() method but rather via, for example, a synchronized queue monitored by a Swing timer that inspects it periodically. All bets are off, of course, if the data is transferred via some unsynchronized means. This applies more generally to any cross-thread communication mechanism. Even if not using the EDT, there is likely some synchronized data-transfer mechanism that acts as the go-between, allowing that newly constructed reference to safely move from one thread to the other. So long as the reference is not inserted into that synchronized mechanism until the constructor returns, then the other thread has the full guarantee of the object being fully initialized that the original thread where the object was created has. In other words, even if it turns out that I'm mistaken and the JVM doesn't provide any specific synchronization guarantees with respect to object construction, code that is otherwise thread-safe anyway will automatically ensure that the initialization of the object is itself thread-safe. Note also that this second mechanism applies not just to construction, but to _any_ mutation that may occur in one thread prior to the object being delivered to another thread. Finally, part of your question brings up the possibility of the "Person" object being mutable. And well, yes. If those classes are mutable, there could yet still be a thread-safety problem if they mutate post-construction without synchronization being used between threads handling those objects. But that's not related to the question of the initialization of the object. That would be just the usual "synchronize mutations" problem that generally comes up with concurrent code. Pete |