Multithreading and synchronization is a very important topic for any Java programmer.
Synchronization in Java
Synchronization in Java is possible by using Java keywords "synchronized" and "volatile”.
Concurrent access of shared objects in Java introduces to kind of
errors: thread interference and memory consistency errors and to avoid
these errors you need to properly synchronize your Java object to allow
mutual exclusive access of critical section to two threads.
Need of Synchronization
If your code is executing in multi-threaded environment, you need synchronization for objects,
which are shared among multiple threads, to avoid any corruption of
state or any kind of unexpected behaviour. Synchronization in Java will
only be needed if shared object is mutable. if your shared object is
either read only or immutable object, than you don't need synchronization, despite running multiple threads.
if all the threads are only reading value then you don't require synchronization in Java. JVM guarantees that Java synchronized code will only be executed by one thread at a time.
- synchronized keyword in Java provides locking, which ensures mutual exclusive access of shared resource and prevent data race.
- synchronized keyword also prevent reordering of code statement by compiler which can cause subtle concurrent issue if we don't use synchronized or volatile keyword
- synchronized keyword involve locking and unlocking. before entering into synchronized method or block
thread needs to acquire the lock, at this point it reads data from main
memory than cache and when it release the lock, it flushes write
operation into main memory which eliminates memory inconsistency errors.
You can have both static synchronized method and non static synchronized method and synchronized blocks in Java but we can not have synchronized variable in java.
Using synchronized keyword with variable is illegal and will result in compilation error. Instead of synchronized variable in Java, you can have java volatile variable, which will instruct JVM threads to read value of volatile variable from main memory and don’t cache it locally.
Block synchronization in Java is preferred over method synchronization in Java
because by using block synchronization, you only need to lock the
critical section of code instead of whole method. Since synchronization
in Java comes with cost of performance, we need to synchronize only part
of code which absolutely needs to be synchronized.
Important points
1. Synchronized keyword in Java
is used to provide mutual exclusive access of a shared resource with
multiple threads in Java. Synchronization in Java guarantees that, no
two threads can execute a synchronized method which requires same lock
simultaneously or concurrently.
2. You can use java synchronized keyword only on synchronized method or synchronized block.
3. When ever 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.
4. Java Thread acquires an object level lock
when it enters into an instance synchronized java method and acquires a
class level lock when it enters into static synchronized java method.
5. 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.
6. Java Synchronization will throw NullPointerException if object used in java synchronized block is null e.g. synchronized (myInstance) will throws java.lang.NullPointerException if myInstance is null.
7. One Major disadvantage of Java synchronized keyword
is that it doesn't allow concurrent read, which can potentially limit
scalability. By using concept of lock stripping and using different
locks for reading and writing, you can overcome this limitation of
synchronized in Java. You will be glad to know that java.util.concurrent.locks.ReentrantReadWriteLock provides ready made implementation of ReadWriteLock in Java.
8. One more limitation of java synchronized keyword
is that it can only be used to control access of shared object within
the same JVM. If you have more than one JVM and need to synchronized
access to a shared file system or database, the Java synchronized keyword is not at all sufficient. You need to implement a kind of global lock for that.
9. Java synchronized keyword incurs performance cost.
Synchronized method in Java is very slow and can degrade performance.
So use synchronization in java when it absolutely requires and consider
using java synchronized block for synchronizing critical section only.
10. Java synchronized block is better than java synchronized method
in Java because by using synchronized block you can only lock critical
section of code and avoid locking whole method which can possibly
degrade performance.
11. Its
possible that both static synchronized and non static synchronized
method can run simultaneously or concurrently because they lock on
different object.
12. From java 5 after change in Java memory model reads and writes are atomic for all variables declared using volatile keyword
(including long and double variables) and simple atomic variable access
is more efficient instead of accessing these variables via synchronized
java code.
13. Java synchronized code could result in deadlock or starvation while accessing by multiple thread if synchronization is not implemented correctly.
14. According to the Java language specification you can not use Java synchronized keyword with constructor
it’s illegal and result in compilation error. So you can not
synchronized constructor in Java which seems logical because other
threads cannot see the object being created until the thread creating it
has finished it.
15. You cannot apply java synchronized keyword with variables and can not use java volatile keyword with method.
16. Java.util.concurrent.locks
extends capability provided by java synchronized keyword for writing
more sophisticated programs since they offer more capabilities e.g. Reentrancy and interruptible locks.
17.
Java synchronized keyword also synchronizes memory. In fact java
synchronized synchronizes the whole of thread memory with main memory.
18. Important method related to synchronization in Java are wait(), notify() and notifyAll() which is defined in Object class. They are defined in java.lang.object class instead of java.lang.Thread
19. 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. example of synchronizing on non final field :
private String lock = new String("lock");
synchronized(lock){
System.out.println("locking on :" + lock);
}
20. Its not recommended to use String object as lock in java synchronized block because string is immutable object
and literal string and interned string gets stored in String pool. so
by any chance if any other part of code or any third party library used
same String as there lock then they both will be locked on same object
despite being completely unrelated which could result in unexpected
behavior and bad performance. instead of String object its advised to
use new Object() for Synchronization in Java on synchronized block.
private static final String LOCK = "lock"; //not recommended
private static final Object OBJ_LOCK = new Object(); //better
public void process() {
synchronized(LOCK) {
........
}
}
No comments:
Post a Comment