|
Sleep and Yield
Thread.sleep() causes the current thread to sleep for the
specified milliseconds. Both yield and sleep do not lose the
ownership on the monitor they have acquired. The compilers need
not flush out the values in the registers and reload cached
values from memory during the sleep and yield process.
Finalization
The object class which is the super class of all classes has a
finalize method which is used to do any cleanup operations
before the object’s memory is reclaimed by the garbage
collector. The cleanup is important because orphaned references
remain in memory when an object’s memory is reclaimed. The Java
memory model does not define strict rules on when finalization
will be done by the garbage collector. It is left to JVM
implementations on when finalization should be done. However the
memory model specifies that finalization should be surely done
before a object’s memory is reclaimed.
Volatile Fields
Declaring a variable as volatile is almost similar to having a
synchronized variable. The only difference is that no locking or
unlocking needs to be done. Volatile fields can be useful when
manipulations on a few variables are required and
synchronization can be an overhead. But if too many variables
are declared as volatile in a method they degrade the
performance of the method. In such cases it would be sensible to
declare the method as synchronized.
Data Races
The Java language specification gives compilers flexibility to
order program execution for optimization purposes. This
flexibility can result in programs being ordered differently
from what the programmer would have expected. Let us look at an
example.
public class SynchSample{
private int classVar1 = 0;
private int classVar2=0;
private int outputVar1;
private int outputVar2;
public SysnchSample(){
}
public void doOperation1(){
outputVar1= classVar1;
classVar2 = 4;
}
public void doOperation2(){
outputVar2= classVar2;
classVar1=5;
}
}
Listing 1:
Running this program in a single threaded environment where
doOperation1 and doOperation2 are called one after another would
yield outputVar1=0 and outputVar2= 4. This seems fine, now if
you try to run this program in a multi-threaded environment the
results could be different.
Let us create two threads thread 1 and thread 2, which would
access the same instance (SynchSample object). Thread 1 would
run doOperation1 and thread 2 will run doOperation2. In this
case there is a possibility that either thread 1 or thread 2
would get executed first. In the case when thread 1 is executed
first one would assume that the value of outputVar1 would remain
as 0, but when outputVar1 is displayed it shows a value of 5.
This is an anomaly that programmers do not expect. Though
classVar1 was assigned the value 5 later when the thread 2
executes, the value gets reflected into the outputVar1. This
seems paradoxical but it is the actual behavior exhibited by the
Java memory model. This condition is called a "Data Race".
To avoid this condition of a data race, programs should be
correctly synchronized. The process of synchronization does not
guarantee the proper running of the program but it allows the
programmer to predict the behavior of the program and avoid
undesirable results.
Synchronization can be achieved by defining a happens-
before relationship to actions. When a happens-before
relation is defined for an action, it gets executed before the
subsequent actions and is visible to the subsequent actions.
Though there is no specific construct or command in the Java
language to define a happens-before relationship, it can
be done in many ways like ordering an action before another in a
program and surrounding actions with the synchronized keyword.
The synchronized keyword should be used carefully to avoid
unnecessary overheads on the performance of the program.
Other ways of implementing the happens-before relationship are:
- Using the volatile keyword, which always does a write to
the field before a read can be done.
- Defining actions in the start method of a thread as the
start method is always called before executing any other actions
on the class.
- Using join, every action in a thread is usually executed
before other threads successfully return from a join from that
thread.
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.
|