img
. . . .
Example 6-5 Synchronized Statement
synchronized(foo){
// code to execute with foo's mutex held
}
When you enter the synchronized statement the mutex belonging to the object referred to by foo
will be locked for you, and when you leave the statement, whether normally or via an exception,
the mutex will be unlocked for you. Should the mutex already be locked, the thread will block, as
with POSIX. This syntax makes it impossible to forget to unlock a mutex but also requires that all
uses of mutexes are nested (i.e., you always release mutexes in the reverse order to which you
acquire them). Unlike POSIX, in Java there is no defined wakeup order; even priority levels are
ignored.
As a shorthand notation we can define a method to be synchronized, which has the same effect as
placing the entire body of the method in a synchronized statement using the current object as the
object to lock. The two bits of code shown in Code Example 6-6 behave identically.
Example 6-6 Using synchronized in Java
Explicit Synchronization
Implicit Synchronization
public MyClass() {
public MyClass() {
int count = 0;
int count = 0;
void frob() {
void synchronized frob() {
synchronized(this) {
count++;
count++;
}
}
}
}
}
The mutex that will be used is gotten from the object referenced, either the object the method is
running on (for the implicit case) or from the object specifically mentioned (for the explicit case).
The class Object (and hence any subclass, that is, every class) has two private instance
variables.[5] One is a mutex, the other is a wait set, which we'll discuss soon. Primitive types (int,
char, etc.) do not inherit from Object and hence do not have associated mutexes and wait sets.
[5]
It may seem rather expensive to allocate a few dozen bytes for every single object, especially
when very few mutexes or wait sets ever get used. It would be if they were actually allocated every
time. Clever systems programmers avoid this space overhead by a couple of tricks.
It is important to realize that the mutex and wait set are per object, not per class; thus two different
instances of class Foo will have two different mutexes (see Figure 6-5) and locking one will not
protect data used by the other. So the code in Code Example 6-5 is correct because each instance
of MyClass will have its own instance of count. If count had been declared to be static, the
code would not have worked.
Figure 6-5. Each Instance Has Its Own Mutex
Search WWH :
Custom Search
Previous Page
Multithreaded Programming with JAVA - Topic Index
Next Page
Multithreaded Programming with JAVA - Bookmarks
Home