Friday, September 15, 2023

The Ultimate Guide of Synchronization in Java - Examples

Multithreading and synchronization are a very important topic for any Java programmer. Good knowledge of multithreading, synchronization, and thread-safety can put you in front of other developers, at the same time, it's not easy to master this concept. In fact, writing correct concurrent code is one of the hardest things, even in Java, which has several inbuilt synchronization utilities. In this Java synchronization tutorial we will learn what is meaning of Synchronization in Java, Why do we need Synchronization in Java, What is java synchronized keyword, examples of using Java synchronized method and blocks, What can happen in multithreading code in absence of synchronized constructs, tips to avoid mistakes, while locking critical section in Java and some of the important points about synchronization in Java.

Java provides different constructs to provide synchronization and locking e.g. volatile keyword, atomic variable, explicitly locking using java.util.concurrent.lock.Lock interface and their popular implementations e.g. ReentrantLock and ReentrantReadWriteLock, It becomes even more important to understand the difference between synchronized and other constructs. 

Remember, a clear understanding of synchronization is a must to write correct concurrent code in Java, which is free of multithreading issues like deadlock, race conditions, and thread safety. I am sure, things learned in this Java synchronization tutorial will help. 

Once you went through this article, You can further read Java Concurrency in Practice to develop your concept.  That's one of those books that every Java developer must-read.


1. What is Synchronization in Java?

Synchronization in Java is an important concept since Java is a multi-threaded language where multiple threads run in parallel to complete program execution. In multi-threaded environment synchronization of Java object or synchronization of Java class becomes extremely important

Synchronization in Java is possible by using the Java keywords "synchronized" and "volatile”

Concurrent access of shared objects in Java introduces two kinds 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. 

By the way, This Java Synchronization tutorial is in continuation of my article How HashMap works in Java and the difference between HashMap and Hashtable in Java if you haven’t read it already you may find some useful information based on my experience in Java Collections.



2. Why do we need Synchronization in Java?

If your code is executing in a 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 behavior. 

Synchronization in Java will only be needed if a shared object is mutable. if your shared object is either a read-only or immutable object, then you don't need synchronization, despite running multiple threads. 

The same is true with what threads are doing with an object if all the threads are only reading values then you don't require synchronization in Java. JVM guarantees that Java synchronized code will only be executed by one thread at a time

In Summary, Java synchronized Keyword provides the following functionality essential for concurrent programming:

1. The synchronized keyword in Java provides locking, which ensures mutually exclusive access to the shared resource and prevents data race.

2. synchronized keyword also prevents reordering of code statement by the compiler which can cause a subtle concurrent issue if we don't use synchronized or volatile keywords.

3. synchronized keyword involves locking and unlocking. before entering into a synchronized method or block thread needs to acquire the lock, at this point it reads data from main memory than cache and when it releases the lock, it flushes write operation into main memory which eliminates memory inconsistency errors.

For more details, read Java Concurrency in Practice twice, if you have not read it already:






3. Synchronized keyword in Java

java synchronized keyword example , synchronization in java tutorialPrior to Java 1.5 synchronized keyword was the only way to provide synchronization of shared object in Java. Any code written by using  synchronized block or enclosed inside synchronized method will be mutually exclusive, and can only be executed by one thread at a time.


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 a 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 the value of the 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 the whole method. Since synchronization in Java comes with the cost of performance, we need to synchronize only part of the code which absolutely needs to be synchronized.


3.1 Synchronized Method Example in Java

Using synchronized keyword along with method is easy just apply synchronized keyword in front of the method. What we need to take care is that static synchronized method locked on class object lock and non-static synchronized method locks on current object (this)

So it’s possible that both static and non-static java synchronized method running in parallel.  This is the common mistake a naive developer do while writing Java synchronized code.


public class Counter{

  private static int count = 0;

  public static synchronized int getCount(){
    return count;
  }

  public synchoronized setCount(int count){
     this.count = count;
  }

}

In this example of Java, the synchronization code is not properly synchronized because both getCount() and setCount() are not getting locked on the same object and can run in parallel which may result in the incorrect count. 

Here getCount() will lock in Counter.class object while setCount() will lock on current object (this). To make this code properly synchronized in Java you need to either make both method static or nonstatic or use java synchronized block instead of java synchronized method.

By the way, this is one of the common mistake Java developers make while synchronizing their code.


3.2 Synchronized Block Example in Java

Using synchronized blocks in java is also similar to using synchronized keyword in methods. Only important thing to note here is that if object used to lock synchronized block of code, Singleton.class in below example is null then Java synchronized block will throw a NullPointerException.

public class Singleton{

private static volatile Singleton _instance;

public static Singleton getInstance(){
   if(_instance == null){
            synchronized(Singleton.class){
              if(_instance == null)
              _instance = new Singleton();
            }
   }
   return _instance;
}

This is a classic example of double checked locking in Singleton. In this example of Java synchronized code, we have made the only critical section (part of the code which is creating an instance of singleton) synchronized and saved some performance. 

If you make the whole method synchronized than every call of this method will be blocked, while you only need blocking to create singleton instance on the first call. By the way, this is not the only way to write thread safe singleton in Java.  You can use Enum, or lazy loading to avoid thread-safety issue during instantiation. 


Synchronization in Java

Even above code will not behave as expected because prior to Java 1.5, double checked locking was broken and even with the volatile variable you can view half initialized object. The introduction of Java memory model and happens before guarantee in Java 5 solves this issue. To read more about Singleton in Java see that.


4. Important points of synchronized keyword in Java

synchronized keywrod java example , synchronization in java tutorial1. Synchronized keyword in Java is used to provide mutually exclusive access to a shared resource with multiple threads in Java. Synchronization in Java guarantees that no two threads can execute a synchronized method which requires the same lock simultaneously or concurrently.

2. You can use java synchronized keyword only on synchronized method or synchronized block.

3. Whenever a thread enters into java synchronized method or blocks it acquires a lock and whenever it leaves java synchronized method or block it releases the lock. The 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 the same lock then the current thread which is holding lock can enter into that method without acquiring the lock.

6. Java Synchronization will throw NullPointerException if object used in java synchronized block is null e.g. synchronized (myInstance) will throw 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 the 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 to a shared object within the same JVM. If you have more than one JVM and need to synchronize 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 a performance cost. A 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 the whole method which can possibly degrade performance. A good example of java synchronization around this concept is getting Instance() method Singleton class. See here.

11. It's possible that both static synchronized and non-static synchronized method can run simultaneously or concurrently because they lock on the different object.

12. From java 5 after a change in Java memory model reads and writes are atomic for all variables declared using the volatile keyword (including long and double variables) and simple atomic variable access is more efficient instead of accessing these variables via synchronized java code. But it requires more care and attention from the programmer to avoid memory consistency errors.

13. Java synchronized code could result in deadlock or starvation while accessing by multiple threads if synchronization is not implemented correctly. To know how to avoid deadlock in java see here.

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 synchronize 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 the 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. Do you know, why they are defined in java.lang.object class instead of java.lang.Thread? You can find some reasons, which make sense.

19. Do not synchronize on the non-final field on synchronized block in Java. because the reference of the non-final field may change anytime and then different thread might synchronizing on different objects i.e. no synchronization at all. an example of synchronizing on the non-final field:


private String lock = new String("lock");
synchronized(lock){
    System.out.println("locking on :"  + lock);
}

any if you write synchronized code like above in java you may get a warning "Synchronization on the non-final field"  in IDE like Netbeans and IntelliJIDEA.

20. It's not recommended to use String object as a lock in java synchronized block because a string is an immutable object and literal string and interned string gets stored in String pool. 

So, by any chance if any other part of the code or any third party library used same String as there lock then they both will be locked on the 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) {
      ........
   }
}

21. From Java library, Calendar and SimpleDateFormat classes are not thread-safe and requires external synchronization in Java to be used in the multi-threaded environment.  

and last,

Java Multithreading tutorial


Probably most important point about Synchronization in Java is that in the absence of synchronized keyword or another construct e.g. volatile variable or atomic variable, compiler, JVM, and hardware are free to make optimization, assumption, reordering or caching of code and data, which can cause subtle concurrency bugs in code. By introducing synchronization by using volatile, atomic variable or synchronized keyword, we instruct compiler and JVM to not to do that.

Update 1: Recently I have been reading several Java Synchronization and Concurrency articles on the internet and I come across Jeremy Manson's blog which works in google and has worked on JSR 133 Java Memory Model, I would recommend some of this blog post for every java developer, he has covered certain details about concurrent programming , synchronization and volatility in simple and easy to understand language, here is the link atomicity, visibility and ordering

Update 2:  I am grateful to my readers, who has left some insightful comments on this post. They have shared lots of good information and experience and to provide them more exposure, I am including some of their comments on the main article, to benefit new readers. 

@Vikas wrote
Good comprehensive article about synchronized keyword in Java. to be honest I have never read all these details about synchronized block or method at one place. you may want to highlight some limitation of synchronized keyword in Java which is addressed by explicit locking using new concurrent package and Lock interface:

1. synchronized keyword doesn't allow separate locks for reading and writing. as we know that multiple threads can read without affecting thread-safety of class, synchronized keyword suffer performance due to contention in case of multiple readers and one or few writer.

 2. if one thread is waiting for lock then there is no way to timeout, the thread can wait indefinitely for the lock.
 
3. on a similar note if the thread is waiting for the lock to acquired there is no way to interrupt the thread.
 
All these limitations of synchronized keyword are addressed and resolved by using ReadWriteLock and ReentrantLock in Java 5.

@George wrote
Just my 2 cents on your great list of Java Synchronization facts and best practices:
 
1) synchronized keyword in internally implemented using two-byte code instructions MonitorEnter and MonitorExit, this is generated by the compiler. The compiler also ensures that there must be a MonitorExit for every MonitorEnter in different code paths e.g. normal execution and abrupt execution, because of Exception.

2) java.util.concurrent package different locking mechanism than provided by synchronized keyword, they mostly used ReentrantLock, which internally use CAS operations, volatile variables, and atomic variables to get better performance.
 
3) With synchronized keyword, you have to leave the lock, once you exist a synchronized method or block, there is no way you can take the lock to another method. java.util.concurrent.locks.ReentrantLock solves this problem by providing control of acquiring and releasing the lock, which means you can acquire the lock in method A and can release in method B if they both need to be locked in the same object lock. 

Though this could be risky as the compiler will neither check nor warn you about any accidental leak of locks. This means, this can potentially block other threads, which are waiting for the same lock.

4) Prefer ReentrantLock over synchronized keyword, it provides more control on lock acquisition, lock release, and better performance compared to synchronized keyword.
 
5) Any thread trying to acquire a lock using a synchronized method will block indefinitely until the lock is available. Instead this, tryLock() method of java.util.concurrent.locks.ReentrantLock will not block if the lock is not available.
Having said that, I must say, lots of good information.

And lastly one question for you? What is difference between atomic, synchronized, and volatile keywords in Java? Can you use atomic variables in place of synchronized keyword? or can you replace synchronized with volatile in Java?

42 comments :

Unknown said...

I think that the "double checked locking" example that you gave have to use the volatile keyword to be correct.

Javin @ FIX Protocol Tutorial said...

Hi alias , you are correct to keep Singleton as Singleton that has to be volatile but that example was just to show use of synchronized block instead of getInstance() method but no harm on putting volatile there :) Thanks

Unknown said...

You cannot use volatile on a methode, the keyword is for variable. Your Singleton example won't compile.

Javin @ FIX Protocol and Electroinc Trading said...

@Arnaud Vandyck , Thanks for pointing out, It was a typo , volatile indeed only applicable to variable and was intended for Singleton instance but some how placed on method signature. I will correct them. Thanks

Javin @ FIX Protocol and Electroinc Trading said...

@Anonymous, good to hear that you like the post. Indeed synchronization is very important topic specially if you are working with online stock trading companies or any electronic trading platform which are designed to be concurrent for high volume and low latency.

Anonymous said...

Nice Blog on synchronisation(for that matter a lot of topics)...got to know the knick knacks of java ...thanx to u:)
Keep up ur good work. Kudos!

Anonymous said...

What is synchronization in Java and Why do we need it ? Can you give example of synchronization in java ? What will happen if we don't have synchronization in Java ???

Anonymous said...

@Anonymous , Synchronization in Java means allowing controlled access of a shared resource to avoid problem like deadlock. java is a multi-threaded language which gives you ability to write high performance concurrent programs which can benefit from high end multi-core processors. you can use synchronized and volatile keyword to achieve synchronization in java. and if you read this tutorial you will see example of using synchronized block and synchronized method in java.

Peter Lawrey said...

s/synchoronized/synchronized/ ;)

javin paul said...

thanks Peter done s/synchoronized/synchronized/, only one match found :)

Rajesh Kumar said...

Thanks for giving the detailed explanation on thread synchronization. If possible, please do expand the article by showing usefulness of wait(), notify(), notifyAll() methods in synchronization.

Anonymous said...

Most Informative article on Java Synchronization, Never know there is so much to learn on synchronization in Java. you have covered almost everything form synchronized method to synchronized block to some really less known points on Synchronization. Though its more focus on Java and Synchronization , this kind of article on any topic is quite useful.

Javin @ thread vs runnable java said...

Hi Abdul, Thanks for your comment and you like this Java synchronization tutorial. keep the good work in your blog as well.

Jeff R said...

You have quite a few compiler errors in your Counter class. But the biggest problem is you are attempting to access 'this' from a static method. Instead you should use the class name Counter since count is a static variable.

Javin @ thread safe class in java said...

Hi Jeff R, Thanks for your comment. I see your point, this should not be used to access static variable but code is not written to be compilation there. It just to show that static and non static synchronized method lock on two different object so it effectively means no mutual exclusive access because two thread can concurrently run static and non static methods. Anyway its always better to have clean code , so I will correct that. thanks for pointing.

skplife said...

nice selection of book.These books are very helpful for experience persons who are working on java

Javin @ final variable java said...

Thanks skplife, Glad you like the books, Effective Java and Java Concurrency in Practice for multi-threading and synchronization is must read for any Java developer.

Anonymous said...

Interesting article. The heading promises that it will tell us how synchronization works. Instead it only tells us how to use synchronization. Disappointed...

Anonymous said...

Hello there :) me again...
There's a small gap here:
"Lock is released .... or due to any Error or Exception"

The thread does NOT release the lock when an exception is thrown, and the program stalls indefinitely.hence a kind of deadlock appears, since the second thread cannot acquire the Lock that thread 1 acquired, and did not released it;
I coded a small example in this morning, we can check together :)
================================================

class HoldingLockWhenException {
private boolean isLocked = false;

private class Foo implements Runnable {
public void run() {
synchronized(HoldingLockWhenException.this) {
System.out.println(Thread.currentThread().getName() + " acquired the Lock on outer this");
if(!isLocked)
throw new IllegalThreadStateException();

isLocked = true;
HoldingLockWhenException.this.notify();
}
}
}
private class Bar implements Runnable {
public void run() {
synchronized(HoldingLockWhenException.this) {
System.out.println(Thread.currentThread().getName() + " acquired the Lock on outer this");
while(!isLocked) {
try {
HoldingLockWhenException.this.wait();
} catch(InterruptedException interx) {}
}
System.out.println(Thread.currentThread().getName() + " process further");
}
}
}
public static void main(String[] argv) {
HoldingLockWhenException outer = new HoldingLockWhenException();
Thread run1 = new Thread(outer.new Foo());
Thread run2 = new Thread(outer.new Bar());
run1.start();
run2.start();
}
}
================================================

Anonymous said...

@Anonymous

The lock release occurs even if the return was caused by an uncaught exception.

Source : http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Anonymous said...

If we used synchronized in singleton class it will allow to access the object for only one user. if 100 users wants to access the same object then it has to take some seconds of time to release the lock for every user like that how much time it takes for 100th user? In this scenario, how can we handle ?

Karen said...

I'm not understanding why the double checked locking code would throw a null pointer exception. The code is identical to the ones here http://javarevisited.blogspot.sg/2011/06/volatile-keyword-java-example-tutorial.html

Anonymous said...

public class Letters extends Thread {
private String name;
public Letters(String name) { this.name = name; }
public void write() {
System.out.print(name);
System.out.print(name);
}
public static void main(String[] args) {
new Letters("X").start();
new Letters("Y").start();
}


public void run() { synchronized(this) { write(); } }



}


Output i m getting sometimes is XYYX . I am thinking because write method is synchronized here , so write method would be locked on current object and it should be either XXYY or YYXX. Tell me what's wrong in my concept?? I m not getting here.

Javin @ Java Classloder Working said...

@Anonymous

- I don't see synchronized keyword on write() method.
- you are using two different thread and two different object, which means there is effectively no locking. In your current code, try making write() method static synchronized.

Radhika said...

In one of Interview, I was asked couple of questions from Java Synchronization, It would be good if you can answer this here:

Can you synchronize on local variable or non final variable in Java? If you do, what problem will you face?

Why Object Lock should be private, if used to lock a critical section?

My answer to the first question was YES. Java Synchronization allows you to use local variable or non final field to lock synchronized block, but I couldn't answer risk part.

For second question also, I got confused that what will happen if made Object lock non public or protected?

Unknown said...

Hi...i have some issue with synchronization....please help me.
My application is a swing application. I have a button. The button action code is below

LabelStatus.setText("searching");
BluetoothBrowser.main(null);

BluetoothBrowser class contain synchronized block. Now my problem is when i am click on the button it doesn't display the text on the LabelStatus. What is wrong with my code

javin paul said...

check if BluetoothBrowser.main(null); is blocking call or not, since event handling and graphics drawing is done by Event dispatcher thread, it won't draw anything until it return from your action listener code.

Anonymous said...

@Radhika
Yes we can use local variable or non final variable for synchronization but they will or may lead you to the problems.
1. Since new local variables gets created for every call to the method so there is no point in synchronizing on local variable because another thread running in same method will be having different object in same variable.

2. Similarly for non final variable just imagine the case if i change the object reference in non final variable.

I hope you can think of the problem now. :)
Vipni

Unknown said...

For anyone interested in what the JVM does:
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.14

Anonymous said...

Under the section "Important points of synchronized keyword in Java" #19 'Do not synchronize on non final field on synchronized block in Java' example, isn't the String class object final by default.

Arun Singh said...

Your tutorial is very good. Thanks

javin paul said...

Thank you Arun, glad you find my tutorials useful.

Unknown said...

this sould not compile in java 9 becausec '_'character resereved for
for lambda expresssion

Unknown said...

hi,javin i have two problem about your article :

first :volatile can't promise atom action for example i++ instruction.

second:sychornized keyword if can prevent reordering of coding ,then in double check lock volatile whether can not exists

Unknown said...

Can u please help me in getting synopsis for synchronization in java for mini project

Unknown said...

we have local variables to resolve thread safety issues ,never use instance variables.why synchronised is introduced when we have local variables .At code Design level itself we can eliminate thread related problems .Whats difference between local variable vs synchronised vs instance variables?

Unknown said...

bhai sahab saral bhasa me dalo yr ye to kuch smj me ni aaya humare

Unknown said...

i need the exact definition of synchronization

Anonymous said...

Question. I have two classes with different methods using a synchronized blocks that use the same object for locking. It doesn't appear that one object holding the lock prevents the other objects sync block from running. Is this expected behavior?

javin paul said...

@Anonymous, the synchronization will happen if two threads will try to get into those two methods and lock is held by other. If you just have one thread or if method is doing nothing, you won't notice that behavior. If you want to confirm then start with two threads and put some sleep on both method. Alternative, just put a break-point on each method and debug, you will know the truth.

Kipper Li said...

I have a question here. we can use syntax like synchronized(Object.class) {//do some logic here}. What does synchronized real locked? If it locked class object of 'Object'(Top class of all java class) class. then we know the .class object is singleton in whole JVM if they are load by same classloader. In another word, all any other thread wants to access .class object's method, it will be blocked? Luckily, .class object only has normal method without any synchronized method. my understanding Is it right?

javin paul said...

yes, that's correct. Object.class is only one object so every other thread will be blocked when one thread is accessing it.

Post a Comment