Object Level vs Class Level Lock
Example to understand Object and Class level locks in Java
A) Object Level lock example
package com.test;
public class Foo implements Runnable {
@Override
public void run() {
Lock();
}
public void Lock() {
System.out.println(Thread.currentThread().getName());
synchronized(this) {
System.out.println("in block " + Thread.currentThread().getName());
System.out.println("in block " + Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Foo b1 = new Foo();
Thread t1 = new Thread(b1);
Thread t2 = new Thread(b1);
Foo b2 = new Foo();
Thread t3 = new Thread(b2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
output:
t1
t3
t2
in block t3
in block t1
in block t3 end
in block t1 end
in block t2
in block t2 end
Note that t3 will not block when threads t1 and t2 block. Because the lock is placed on this object and thread t3 has different this object than thread t1, t2.
B) Class Level lock example
The code in object level lock, only Foo.class is added in synchronized block. All the threads are getting created using object of Foo class will get blocked.
package com.test;
public class Foo implements Runnable {
@Override
public void run() {
Lock();
}
public void Lock() {
System.out.println(Thread.currentThread().getName());
synchronized(Foo.class) {
System.out.println("in block " + Thread.currentThread().getName());
System.out.println("in block " + Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Foo b1 = new Foo();
Thread t1 = new Thread(b1);
Thread t2 = new Thread(b1);
Foo b2 = new Foo();
Thread t3 = new Thread(b2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
output:
t1
t3
in block t1
in block t1 end
t2
in block t3
in block t3 end
in block t2
in block t2 end
Synchronized block is going to be executed for the same thread.
Important things:
Synchronization in java guarantees that no two threads can execute a synchronized method which requires same lock simultaneously or concurrently.
Synchronized keyword can be used only with methods and code blocks. These methods or blocks can be static or non-static both.
Whenever a thread enters into java synchronized method or block it acquires a lock and whenever it leaves java synchronized method or block it releases the lock. Lock is released even if thread leaves synchronized method after completion or due to any Error or Exception.
java synchronized keyword is re-entrant in nature it means if a java synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock.
Java Synchronization will throw NullPointerException if object used in java synchronized block is null. For example, in above code sample if lock is initialized as null, the synchronized (lock) will throw NullPointerException.
Synchronized methods in Java put a performance cost on your application. So use synchronization when it is absolutely required.
Also, consider using synchronized code blocks for synchronizing only critical section of your code. It’s possible that both static synchronized and non-static synchronized method can run simultaneously or concurrently because they lock on different object.
According to the Java language specification you cannot use java synchronized keyword with constructor it’s illegal and result in compilation error.
Do not synchronize on non-final field on synchronized block in Java. Because reference of non-final field may change any time and then different thread might synchronizing on different objects i.e. no synchronization at all. Best is to use String class, which is already immutable and declared final.
Comments
Post a Comment