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
No comments:
Post a Comment