Re: Question about synchronized
- From: Matthias Kaeppler <void@xxxxxxxx>
- Date: Sat, 12 Nov 2005 15:53:58 +0100
John C. Bollinger wrote:
As far as I can tell, if M1 is called by A, a lock is acquired on O and thus each call to M2 in B's context will result in the VM inserting B in the wait set until M1 has finished (this is only because M1 is synchronized).
No, that's not entirely correct. Thread A does lock O's monitor once at each entry to M1, and it unlocks the monitor once at each exit from M1, but that has no effect on any thread invoking /unsynchronized/ method M2.
I see.
But what if M2 is called on O in B's context /first/ (remember it's not synchronized), and no lock is acquired on O, and while it's still computing, the VM decides to give A the CPU?
Will M1 now be able to work on O, even though M2 hasn't finished yet?
Yes. You should think of synchronization as protecting sections of code -- either blocks or methods -- not objects. It is in fact mostly a convenience that every object /has/ a monitor at all; the object whose monitor you use to synchronize a particular block of code does not have to have any particular relation to the class that owns the code. Synchronized methods automatically synchronize on the object they are invoked on, but with a synchronized block you specify which object's monitor is used. This is very important.
Yes, I was aware of the difference between synchronized being used as a statement as opposed to being used as a modifier for methods, but I wasn't sure about the mechanics between sychronized blocks of code (or methods) and such that aren't synchronized.
In other words, is in my case of two functions, two threads and one object the program only thread safe if /both/ methods M1 and M2 are declared synchronized? And what effects could arise from one being not not while the other is?
If both M1 and M2 are synchronized then no more than one thread will ever execute in either one of them (collectively) at any particular time. This may be sufficient for thread safety, but it is not certain to be sufficient. The canonical example here is the Collections classes: suppose I have a Collection whose methods are all synchronized. Thread T1 gets the Collection's iterator and starts iterating through the elements. Meanwhile, thread T2 adds an element to the Collection in between T1's invocations of next(). The synchronization ensures that the Collection's internal state remains consistent and means that there is no data race in the sense that that term is used in the latest Java language spec. The synchronization of the individual methods does not prevent T1 from receiving a ConcurrentModificationException. The solution in this case is to put the whole iteration inside a block synchronized on the Collection.
To get a grip on multithreaded programming in Java it is also important to understand the use and effects of Object.wait(), .notify(), and .notifyAll(), and to appreciate the nondeterminism of the thread scheduler. Those are topics for another post, however.
That was quite insightful, thanks.
Regards, Matthias .
- References:
- Question about synchronized
- From: Matthias Kaeppler
- Re: Question about synchronized
- From: John C. Bollinger
- Question about synchronized
- Prev by Date: Re: Question about synchronized
- Next by Date: Re: Garbage collection question?
- Previous by thread: Re: Question about synchronized
- Next by thread: Re: Question about synchronized
- Index(es):
Relevant Pages
|