Synchronization
At times when more than one thread try to access a shared resource, we need to ensure that resource will be used by only one thread at a time. The process by which this is achieved is called synchronization. The synchronization keyword in java creates a block of code referred to as critical section.
Every Java object with a critical section of code gets a lock associated with the object. To enter critical section a thread need to obtain the corresponding object's lock.
General Syntax :
synchronized (object) { //statement to be synchronized }
Why we use Syncronization ?
If we do not use syncronization, and let two or more threads access a shared resource at the same time, it will lead to distorted results.
Consider an example, Suppose we have two different threads T1 and T2, T1 starts execution and save certain values in a file temporary.txt which will be used to calculate some result when T1 returns. Meanwhile, T2 starts and before T1 returns, T2 change the values saved by T1 in the file temporary.txt (temporary.txt is the shared resource). Now obviously T1 will return wrong result.
To prevent such problems, synchronization was introduced. With synchronization in above case, once T1 starts using temporary.txt file, this file will be locked(LOCK mode), and no other thread will be able to access or modify it until T1 returns.
Using Synchronized Methods
Using Synchronized methods is a way to accomplish synchronization. But lets first see what happens when we do not use synchronization in our program.
Example with no Synchronization
class First { public void display(String msg) { System.out.print ("["+msg); try { Thread.sleep(1000); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println ("]"); } } class Second extends Thread { String msg; First fobj; Second (First fp,String str) { fobj = fp; msg = str; start(); } public void run() { fobj.display(msg); } } public class Syncro { public static void main (String[] args) { First fnew = new First(); Second ss = new second(fnew, "welcome"); Second ss1= new second (fnew,"new"); Second ss2 = new second(fnew, "programmer"); } }
Output :
[welcome [ new [ programmer] ] ]
In the above program, object fnew of class First is shared by all the three running threads(ss, ss1 and ss2) to call the shared method(void display). Hence the result is unsynchronized and such situation is called Race condition.
Synchronized Keyword
To synchronize above program, we must serialize access to the shared display() method, making it available to only one thread at a time. This is done by using keyword synchronized with display() method.
synchronized void display (String msg)
Using Synchronised block
If you have to synchronize access to object of a class that has no synchronized methods, and you cannot modify the code. You can use synchronized block to use it.
class First { public void display(String msg) { System.out.print ("["+msg); try { Thread.sleep(1000); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println ("]"); } } class Second extends Thread { String msg; First fobj; Second (First fp,String str) { fobj = fp; msg = str; start(); } public void run() { synchronized(fobj) //Synchronized block { fobj.display(msg); } } } public class Syncro { public static void main (String[] args) { First fnew = new First(); Second ss = new second(fnew, "welcome"); Second ss1= new second (fnew,"new"); Second ss2 = new second(fnew, "programmer"); } }
Output :
[welcome] [new] [programmer]
Because of synchronized block this program gives the expected output.