 |
 |
Under the Hood
How the Java virtual machine performs thread synchronization
The last in a series on Java bytecode, this article covers threads, shared data, locks, and more!

Printer-friendly version | Mail this to a friend
Page 2 of 2
Multiple locks A
single thread is allowed to lock the same object multiple times. For
each object, the JVM maintains a count of the number of times the
object has been locked. An unlocked object has a count of zero. When a
thread acquires the lock for the first time, the count is incremented
to one. Each time the thread acquires a lock on the same object, a
count is incremented. Each time the thread releases the lock, the count
is decremented. When the count reaches zero, the lock is released and
made available to other threads. Synchronized blocks
In Java language terminology, the coordination of multiple threads that must access shared data is called synchronization. The language provides two built-in ways to synchronize access to data: with synchronized statements or synchronized methods.
Synchronized statements To create a synchronized statement, you use the synchronized keyword with an expression that evaluates to an object reference, as in the reverseOrder() method below:
class KitchenSync {
private int[] intArray = new int[10];
void reverseOrder() {
synchronized (this) {
int halfWay = intArray.length / 2;
for (int i = 0; i < halfWay; ++i) {
int upperIndex = intArray.length - 1 - i;
int save = intArray[upperIndex];
intArray[upperIndex] = intArray[i];
intArray[i] = save;
}
}
}
}
In the case above, the
statements contained within the synchronized block will not be executed
until a lock is acquired on the current object (this ). If instead of a this
reference, the expression yielded a reference to another object, the
lock associated with that object would be acquired before the thread
continued.
Two opcodes, monitorenter and monitorexit , are used for synchronization blocks within methods, as shown in the table below.
MONITORS Opcode | Operand(s) | Description | monitorenter | none | pop objectref, acquire the lock associated with objectref | monitorexit | none | pop objectref, release the lock associated with objectref |
When monitorenter
is encountered by the Java virtual machine, it acquires the lock for
the object referred to by objectref on the stack. If the thread already
owns the lock for that object, a count is incremented. Each time monitorexit is executed for the thread on the object, the count is decremented. When the count reaches zero, the monitor is released.
Here is the bytecode sequence generated by the reverseOrder() method of the KitchenSync class.
Note that a catch
clause ensures the locked object will be unlocked even if an exception
is thrown from within the synchronized block. No matter how the
synchronized block is exited, the object lock acquired when the thread
entered the block definitely will be released.
Synchronized methods To synchronize an entire method, you just include the synchronized keyword as one of the method qualifiers, as in:
class HeatSync {
private int[] intArray = new int[10];
synchronized void reverseOrder() {
int halfWay = intArray.length / 2;
for (int i = 0; i < halfWay; ++i) {
int upperIndex = intArray.length - 1 - i;
int save = intArray[upperIndex];
intArray[upperIndex] = intArray[i];
intArray[i] = save;
}
}
}
The JVM does not use
any special opcodes to invoke or return from synchronized methods. When
the JVM resolves the symbolic reference to a method, it determines
whether the method is synchronized. If it is, the JVM acquires a lock
before invoking the method. For an instance method, the JVM acquires
the lock associated with the object upon which the method is being
invoked. For a class method, it acquires the lock associated with the
class to which the method belongs. After a synchronized method
completes, whether it completes by returning or by throwing an
exception, the lock is released. Next month
Now that I have gone through the entire bytecode instruction set, I
will be broadening the scope of this column to include various aspects
or applications of Java technology, not just the Java virtual machine.
Next month, I'll begin a multi-part series that gives an in-depth
overview of Java's security model. 
Page 1 How the Java virtual machine performs thread synchronization
Page 2 Multiple locks
Printer-friendly version | Mail this to a friend
About the author
Bill Venners
has been writing software professionally for 12 years. Based in Silicon
Valley, he provides software consulting and training services under the
name Artima Software Company.
Over the years he has developed software for the consumer electronics,
education, semiconductor, and life insurance industries. He has
programmed in many languages on many platforms: assembly language on
various microprocessors, C on Unix, C++ on Windows, Java on the Web. He
is author of the book: Inside the Java Virtual Machine, published by McGraw-Hill.
Resources
- The book The Java virtual machine Specification (http://www.aw.com/cp/lindholm-yellin.html), by Tim Lindholm and Frank Yellin (ISBN 0-201-63452-X), part of The Java Series (http://www.aw.com/cp/javaseries.html), from Addison-Wesley, is the definitive Java virtual machine reference.
Previous "Under The Hood" articles:
- "The Lean, Mean Virtual Machine" Gives an introduction to the Java virtual machine.
- "The Java Class File Lifestyle" Gives an overview to the Java class file, the file format into which all Java programs are compiled.
- "Java's Garbage-Collected Heap" Gives an overview of garbage collection in general and the garbage-collected heap of the Java virtual machine in particular.
- "Bytecode Basics"
Introduces the bytecodes of the Java virtual machine, and discusses
primitive types, conversion operations, and stack operations in
particular.
- "Floating Point Arithmetic" Describes the Java virtual machine's floating-point support and the bytecodes that perform floating point operations.
- "Logic and Arithmetic" Describes the Java virtual machine's support for logical and integer arithmetic, and the related bytecodes.
- "Objects and Arrays" Describes how the Java virtual machine deals with objects and arrays, and discusses the relevant bytecodes.
- "Exceptions" Describes how the Java virtual machine deals with exceptions, and discusses the relevant bytecodes.
- "Try-Finally" Describes how the Java virtual machine implements try-finally clauses, and discusses the relevant bytecodes.
- "Control Flow" Describes how the Java virtual machine implements control flow and discusses the relevant bytecodes.
- "The Architecture of Aglets" Describes the inner workings of Aglets, IBM's autonomous Java-based software agent technology.
- "The Point of Aglets" Analyzes the real-world utility of mobile agents such as Aglets, IBM's autonomous Java-based software agent technology.
- "Method Invocation and Return" Explains how the Java virtual machine invokes and returns from methods, including the relevant bytecodes.
|
 |