Working With Synchronization in Java

Synchronization

 
A very interesting feature of Java objects is that they are "lockable" objects. That is the java.lang.Object class implements an implicit locking mechanism that allows any Java object to be locked during the execution of a synchronized method or synchronized block. So that the thread that holds the lock gains exclusive access to the object for the duration of the method call or scope of the block. No other thread can "acquire" the object until the thread that holds the lock "releases" the object. This synchronization policy provides mutual exclusion.
 
Synchronized methods are methods that lock the object on entry and unlock the object on exit. The object class implements some special methods for allowing a thread to explicitly release the lock while in the method, wait indefinitely or for some time interval, and then try to reacquire the lock when some condition is true. Two other methods allow a thread to signal waiting thread(s) to tell them to wakeup: the notify method signals one thread wakeup and notifyAll method signals all threads to wake up and compete to try to re-acquire the lock on the object. This type of synchronized object is typically used to protect some shared resource using two types of methods.

Synchronized method

 
The synchronized method declaration qualifiers syntactic sugar for the fact that the entire scope of the procedure is to be governed by the mutual exclusion condition obtained by acquiring the object's lock.

Syntax
 
public synchronized void consume()
{
     while(!consumable())
     {
          //release the lock and wait for the resource
            wait();
       
}
      //have exclusive access to the resource
}

public synchronized void produce()
{
      // change of state must result in the consumable condition being true.
       notifyAll();
      //notify the all waiting threads to try consuming
}


Synchronized Block


A synchronized block allows the granularity of a lock to be finer-grained than a procedure scope. The argument given to the synchronized block is a reference to an object. What about recursive locking of the same object?

Syntax

public void consume()
{
    // code of consuming
}
 
Example: This program has a synchronized block.
  1. class A  
  2. {  
  3.     void callable(String message)  
  4.     {  
  5.         System.out.println(message);  
  6.         try  
  7.         {  
  8.             Thread.sleep(1000);  
  9.         }  
  10.         catch (InterruptedException e)  
  11.         {  
  12.             System.out.println("Interrupted");  
  13.         }  
  14.     }  
  15. }  
  16. class B implements Runnable  
  17. {  
  18.     String message;  
  19.     A obj_A1;  
  20.     Thread t;  
  21.     public B(A1 obj_A2, String s)  
  22.     {  
  23.         obj_A1 = obj_A2;  
  24.         message = s;  
  25.         t = new Thread(this);  
  26.         t.start();  
  27.     }  
  28.   
  29.     //using synchronize block  
  30.     public void run()  
  31.     {  
  32.         synchronized(obj_A1)  
  33.         {  
  34.             obj_A1.callable(message);  
  35.         }  
  36.     }  
  37. }  
  38. //this the main class having main method  
  39. class SynchronizedDemo  
  40. {  
  41.     public static void main(String args[])  
  42.     {  
  43.         A obj_A1 = new A();  
  44.         B b1 = new B(obj_A1, "Excution line one[1] ");  
  45.         B b2 = new B(obj_A1, "Excution line two[2]");  
  46.         B b3 = new B(obj_A1, "Excution line Three[3]");  
  47.         // wait for threads to end  
  48.         try  
  49.         {  
  50.             b1.t.join();  
  51.             b2.t.join();  
  52.             b3.t.join();  
  53.         }  
  54.         catch(InterruptedException e)  
  55.         {  
  56.             System.out.println("Interrupted");  
  57.         }  
  58.     }  
  59. }  
Output
 
synchronization.gif
 
In this program if we are not using the synchronized block then the output might be different: they might not execute in asynchronous order:
 //without using synchronized block.

   public void run()
    {
         obj_A1.callable(message);
    }
 
Example: This program has a synchronized block. 
  1. class A1  
  2. {  
  3.     void callable(String message)  
  4.     {  
  5.         System.out.println(message);  
  6.         try  
  7.         {  
  8.             Thread.sleep(1000);  
  9.         }  
  10.         catch (InterruptedException e)  
  11.         {  
  12.             System.out.println("Interrupted");  
  13.         }  
  14.     }  
  15. }  
  16. class B implements Runnable  
  17. {  
  18.     String message;  
  19.     A1 obj_A1;  
  20.     Thread t;  
  21.     public B(A1 obj_A2, String s)  
  22.     {  
  23.         obj_A1 = obj_A2;  
  24.         message = s;  
  25.         t = new Thread(this);  
  26.         t.start();  
  27.     }  
  28.   
  29.     //using synchronize block  
  30.     public void run()  
  31.     {  
  32.         obj_A1.callable(message);  
  33.     }  
  34. }  
  35. //this the main class having main method  
  36. class SynchronizedDemo  
  37. {  
  38.     public static void main(String args[])  
  39.     {  
  40.         A1 obj_A1 = new A1();  
  41.         B b1 = new B(obj_A1, "Excution line one[1] ");  
  42.         B b2 = new B(obj_A1, "Excution line two[2]");  
  43.         B b3 = new B(obj_A1, "Excution line Three[3]");  
  44.         // wait for threads to end  
  45.         try  
  46.         {  
  47.             b1.t.join();  
  48.             b2.t.join();  
  49.             b3.t.join();  
  50.         }  
  51.         catch(InterruptedException e)  
  52.         {  
  53.             System.out.println("Interrupted");  
  54.         }  
  55.     }  
  56. }  
Output
 
asynchronization.gif
 

Summary

 
In this article, we learned about synchronization in Java and we can use the synchronized methods and blocks in our Java Programs. 
 
For more information about Synchronization, Click


Similar Articles