Java Memory Model
by Benoy Jose
Introduction
The Java Language specification has a whole chapter dedicated
to explaining how threads and the Java memory model works, but
the implementation details of the memory model are minimal and
cause a lot of confusion. The Java specification
only defines rules on how threads should work and how memory
should be managed while the details were left out to individual
implementations of the JVM. Since the rules were not well
detailed they leave a lot of flexibility to the JVM implementers
on how they manage memory and handle threads. As a result of
this we have JVM implementations that adhere to all the rules in
the Java specification while they add their own optimizations to
the JVM to make it run faster. So memory management and thread
management are confusing to the programmers. The JSR 133 tries
to explain the memory model in detail and show how the JVM deals
with threads and the memory. The specification attempts to
explain how incorrectly designed applications can behave in
erroneous ways because the JVM implementation might optimize the
program to run faster.
Memory Model
A memory model defines the possible scenarios and rules that
govern multiple threads in a system. A memory model determines
if an execution trace of a program is legally allowed by the
JVM. The Java specification does not force JVM implementations
to follow any particular implementation rules for program
execution; this gives the JVM implementer flexibility to provide
compiler optimizations and reorganizations in the execution
order. However the memory model specifies that all
implementations produce results that can be predicted by a
programmer. The Memory model defines the possible rules for
threads and the expected behavior of multi-threaded programs so
that programmers can design their programs accordingly. The
responsibility of avoiding data races and deadlock conditions in
threads still lies with the implementer and the programmer.
Features
Synchronization
The Java Memory model explains synchronization techniques to
make sure data corruption does not take place. Synchronization
can also help to avoid deadlocks between threads and run
programs smoothly. The next section details a condition called
Data Race which will illustrate the advantages of
synchronization further.
Lock
The Java memory model provides for locks on monitors when
synchronization needs to be done. Any thread that needs to
execute a synchronized block in a class, first acquires a lock on
the monitor of that object. When the synchronized code block has
finished executing the lock is released and the object is
accessible to another thread.
Atomic Reads
The Java language specification gives compilers the flexibility
on how operations on 64 bit values should be read and operated
upon. Some implementations and compilers may find it easy to
divide a 64 bit double and long values into two 32 bit and write
them to adjacent locations. The Java memory model treats the
two 32 bit writes as separate writes, so there is a possibility
of a thread seeing a partial value when the virtual machine is
mid-way during a write. To avoid the problem the variable can be
declared as volatile or a reference to the variable can be used
to do operation. Volatile long and volatile double
values are always read as a single atomic unit. It is the same
case with references, irrespective of whether they are declared
as 32 bit or 64 bit values.
Word Tearing
Word Tearing occurs when some processors do not allow for a
single byte to be updated individually. In old processors writes
to memory are done through a word (two bytes), so in these cases
the processor would read the whole word from memory and update
the appropriate byte and then write the word back into memory.
This is called word tearing. In modern processors this problem
does not exist as they allow a single byte to be written to
memory.
Fairness
The Java memory model does not specify any fairness requirement
for threads or preemptive multi-threading. A thread can refuse to
surrender the CPU to another thread and throw the system into
deadlock. The rules for fairness to other threads are defined by
the individual JVM implementations.
Wait Sets
A wait set contains a set of threads for a particular object.
Each object has a wait set that is empty when the object is
first created. Every thread, which invokes a wait command, is
put into the wait set. The wait could be a timed wait or an
indefinite wait.
Notification
Notification occurs when the method notify() or notifyAll() is
executed. The call to notify () will release one arbitrary
thread inside the wait set. The notifyAll releases all the
threads waiting inside a wait set.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|