Sunday, 2 March 2014

Synchronized block

There are some situation where you don't want to synchronize entire method, you want synchronization for particular lines of code, then synchronization block is there to help you
   Synatx
   synchronized ( obj ) {
      // block of code
   }

where obj is a reference to the object whose object-level lock must be acquired before entering the block of code.

Some points to Remember
1. Synchronization is costly operation, i.e, it contains overhead of acquiring and releasing of locks and other thread has to wait until the lock hold is released.

Example consider the below program, which will simply iterate a loop 1000000000 times
   
class WithOutSynchronization implements Runnable{
 public void run(){
  sum();
 }

 public void sum(){
  for(int i=0; i < 1000000000; i++){
  }
 }

 public static void main(String args[]) throws Exception{
  WithOutSynchronization task1 = new WithOutSynchronization();
  Thread t1 = new Thread(task1);
  Thread t2 = new Thread(task1);

  long time1 = System.currentTimeMillis();
  t1.start();
  t2.start();
  t1.join();
  t2.join();
  long time2 = System.currentTimeMillis();

  System.out.println("Time taken is " + (time2-time1));
 }
}
   
Output
Time taken is 5

will modify the above program, by applying synchronization

class WithSynchronization implements Runnable{
 public void run(){
  sum();
 }

 public void sum(){
  for(int i=0; i < 1000000000; i++){
   synchronized(this){
   }
  }
 }

 public static void main(String args[]) throws Exception{
  WithSynchronization task1 = new WithSynchronization();
  Thread t1 = new Thread(task1);
  Thread t2 = new Thread(task1);

  long time1 = System.currentTimeMillis();
  t1.start();
  t2.start();
  t1.join();
  t2.join();
  long time2 = System.currentTimeMillis();

  System.out.println("Time taken is " + (time2-time1));
 }
}
   
Output
Time taken is 18014

just compare the two outputs, for the first program with out synchronization takes 5 milliseconds to execute, with synchronization takes 18014 milliseconds to execute.

2. Is there any other situations where I can use synchronized block than synchronized method ?
Yes, of course, will explain with the below program.

Lets us assume there is a bucket, we can insert the elements into the bucket. What we want is, want to insert the elements into the bucket by thread1 at a time, and display the elements. The problem here is other thread also wish to insert. In this race condition we have to use synchronized block.

class BucketDemo{
 int stack[];
 int top = -1, size=0;

 BucketDemo(int size){
  stack = new int[size];
  this.size = size;
 }

 synchronized boolean isSpaceAvailable(){
  return (top < (size-1) );
 }

 synchronized void push(int ele){
  if(isSpaceAvailable()){
   top = top + 1;
   stack[top] = ele;
  }
 }

 void display(){
  for(int i=0; i < size; i++){
   System.out.println(stack[i]);
  }
 }
}

class BucketDemoThread1 implements Runnable{
 BucketDemo obj;

 BucketDemoThread1(BucketDemo obj){
  this.obj = obj;
 }

 public void run(){
  for(int i=0; i < 10; i++){
   obj.push(i);
   try {
    Thread.currentThread().sleep(1000);
   }
   catch(InterruptedException e){
   }
  }
 }
}

class BucketDemoThread2 implements Runnable{
 BucketDemo obj;

 BucketDemoThread2(BucketDemo obj){
  this.obj = obj;
 }

 public void run(){
  for(int i=10; i < 20; i++){
   obj.push(i);
   try{
    Thread.currentThread().sleep(1000);
   }
   catch(InterruptedException e){
   }
  }
 }
}

class SynchronizeBlock {
 public static void main(String args[]) throws Exception{
  BucketDemo obj = new BucketDemo(10);

  BucketDemoThread1 b1 = new BucketDemoThread1(obj);
  BucketDemoThread2 b2 = new BucketDemoThread2(obj);

  Thread task1 = new Thread(b1);
  Thread task2 = new Thread(b2);

  task1.start();
  task2.start();
  task1.join();
  task2.join();

  obj.display();
 }
}
   
Output:
0
10
1
11
12
2
13
3
4
14

but what we are expecting is printing the numbers from 1 to 10 only.

Now apply the synchronized statement to the classes BucketDemoThread1, BucketDemoThread2.

class BucketDemoThread1 implements Runnable{
 BucketDemo obj;

 BucketDemoThread1(BucketDemo obj){
  this.obj = obj;
 }

 public void run(){
  synchronized(obj){
   for(int i=0; i < 10; i++){
    obj.push(i);
    try {
     Thread.currentThread().sleep(1000);
    }
    catch(InterruptedException e){
    }
   }
  }
 }
}

class BucketDemoThread2 implements Runnable{
 BucketDemo obj;

 BucketDemoThread2(BucketDemo obj){
  this.obj = obj;
 }

 public void run(){
  synchronized(obj){
   for(int i=10; i < 20; i++){
    obj.push(i);
    try{
     Thread.currentThread().sleep(1000);
    }
    catch(InterruptedException e){
    }
   }
  }
 }
}

Output
0
1
2
3
4
5
6
7
8
9

synchronized methods                                                 static synchronized methods                                                 Home

No comments:

Post a Comment