Introduction
In my last article “Thread synchronization in Java” we discussed the concept of monitor. A monitor can be compared to a small box that can only carry one thread at once. In the previous example, there is a serialized access to display(). This means that access is restricted to one thread at a time. If the synchronized is omitted from display() method of the class One, all three threads can simultaneously invoke the same method, on the same object. The term "RACE CONDITION" refers to this situation.
Consider an Example, people standing in queue outside a telephone booth, wishing to make call and waiting for their turn, would be similar to synchronized way of accessing data. However, if there was no queue and people were permitted to go in randomly, two or more persons would try to enter the booth at the same time resulting in confusion and chaos. This first instance is similar to concept of synchronization and the second, the concept of race condition.
In general, race conditions in a program are possible when:
- Two or more threads share data
- Two or more threads are reading and writing the shared data simultaneously
Consider once again the same example as we have already discussed in my previous article as below:
class One{
void display(int num){
System.out.print(""+num);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
System.out.println(" Done");
}
}
class Two implements Runnable
{
int number;
One objOne;
Thread objTh;
public Two(One one_num, int num)
{
objOne=one_num;
number=num;
objTh=new Thread(this);
objTh.start();
}
public void run()
{
objOne.display(number);
}
}
class SynchMethod
{
public static void main(String args[])
{
One objOne=new One();
int digit=10;
Two objSynch1=new Two(objOne, digit++);
Two objSynch2=new Two(objOne, digit++);
Two objSynch3=new Two(objOne, digit++);
try
{
objSynch1.objTh.join();
objSynch2.objTh.join();
objSynch3.objTh.join();
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
}
}
In this program, if we removed the keyword synchronized from the entire program, the output will be shown as below:
Using the Synchronized Block
It is not always possible to achieve synchronization by creating synchronized methods within classes. Consider a case where the programmer wants to synchronize access to objects of a class which does not used synchronized methods. It is also assumed that the source code is unavailable because either a third party created it or the class was imported from the built-in library. In such a case, the keyword synchronized cannot be added to the appropriate methods with in the class. Therefore, the problem here would be how to make the access to an object of this class synchronized. This can be achieved by putting all the calls to the methods defined by this class inside a synchronized block.
The general form of synchronized statement is:
synchronized (object)
{
//statement to be synchronized
}
The reference to the object being synchronized is denoted as object.
Curly braces are not required if synchronizing a single sentence. The successful entry of the current thread into the object's monitor is ensured by a synchronized block, which prevents method invocation before that point.
The code below shows how to use the synchronized statement.
//Example for Synchronized Block
class DemoOne
{
void display(int num)
{
System.out.println(""+num);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e) {
System.out.println(" Done");
}
}
}
class DemoTwo implements Runnable
{
int number;
DemoOne objOne;
Thread objTh;
public DemoTwo (DemoOne one_num, int num)
{
objOne=one_num;
number=num;
objTh=new Thread(this);
objTh.start();
}
public void run()
{
synchronized(objOne)
{
objOne.display(number);
}
}
}
class SynchBlock
{
public static void main(String args[])
{
DemoOne objOne=new DemoOne();
int digit=10;
DemoTwo objSynch1=new DemoTwo(objOne, digit++);
DemoTwo objSynch2=new DemoTwo(objOne, digit++);
DemoTwo objSynch3=new DemoTwo(objOne, digit++);
try { //wait for threads to end
objSynch1.objTh.join();
objSynch2.objTh.join();
objSynch3.objTh.join();
}
catch(InterruptedException e)
{
System.out.println("Tnterrupted");
}
}
}
Output
Summary
A software may experience a race condition if Two or more threads share data and At least two threads are simultaneously reading and writing the shared data.