Hello guys, if you are an experienced Java developer say 3 to 5 years or 5 to 7 years experience and preparing for Java Interviews then you very well know that Locking, Synchronization, ConcurrentHashMap, volatile and atomic, compare and swap (CAS), Executor Service, Stream API, and Multithreading in general are quite important and as an experienced Java developer you should be ready for them. In the past, I have shared 50+ Java Multithreading questions, 12 concurrency questions, 21 HashMap questions, and 10 ConcurrentHashMap questions and in this article, I am going to share 10 of my favorite question on Locking, Synchronization and Inter thread communication in Java. If you have been doing Java Interviews then its highly likely that you have already seen this problem but if you haven't you should definitely prepare them.
There has been a lot of articles and books written on how to use wait and notify in Java, how they work, when do you need synchronization, and how to write concurrent code in Java, but, unfortunately, I still see many Java programmer struggles to solve even the classic producer-consumer problem.
I know, writing correct concurrent code is challenging and it takes a lot of practice, think through ability, and experience to get it right, but at the same time, every Java programmer should be familiar with the basics of inter-thread communication, synchronization, locking, and understand how all the things work together.
They should be able to reason the output of the program when the same code is executed by more than one thread, at the same time. They should know that compiler can re-order their code to optimize performance and how they can prevent it.
Since many experienced Java programmer already has a fair idea of the wait, notify, locking, and synchronization concepts, I am not going to explain that, but I'll present interview questions based upon Locking like object lock, monitor, Lock interface and ReentrantLock, Synchronization, and inter thread communication to check and challenge your understanding.
They should be able to reason the output of the program when the same code is executed by more than one thread, at the same time. They should know that compiler can re-order their code to optimize performance and how they can prevent it.
Since many experienced Java programmer already has a fair idea of the wait, notify, locking, and synchronization concepts, I am not going to explain that, but I'll present interview questions based upon Locking like object lock, monitor, Lock interface and ReentrantLock, Synchronization, and inter thread communication to check and challenge your understanding.
And, if you are preparing for core Java interview then my book, Grokking the Java Interview Volume 1 and 2 can help it not only cover multithreading and concurrency but several other important Java topics like Collections, Generics, ClassLoader, Core Java basics, NIO and much more. You can also use code friends20 to get 20% discount.
12 Locking, Synchronization, and Inter-Thread Communication Questions Answer for 3 to 5 Years Experienced Java Programmer
Here is my list of some of the best questions on locking, synchronization, inter-thread communication, and about the wait, notify, and notifyAll methods in Java. These questions are actually asked in several Java interviews and if you have a couple of years of Java experience then you can answer them without any difficulty.1. When do you need synchronization in Java?
First and foremost, as a Java Programmer, you should know when your code needs synchronization. The answer is in the "synchronization motto" coined by Brian Goetz, which says: "If you write a variable which may next be read by another thread, or you are reading a variable which may have been last written by another thread, you must use synchronization".
Suppose you have the following code:
Now, this closed is a boolean field, which may be set by one thread, when the user presses a button and read by another thread that is running this loop. In this case, you need some sort of synchronization so that changes made by one thread are visible to others.
You can achieve that synchronization by using either synchronized or volatile keywords in Java. In fact, it is the right case of using the volatile field, which provides low-cost synchronization.
Now, there are cases, where even though multiple threads execute the code but you don't need any synchronization e.g. reading from HashMap once it is safely initialized. Reading value is a safe operation and can be done without synchronization. provided the value you are reading is not going to change once initialized like final variables.
So, don't say in an interview that if a code is executed by multiple threads then you need synchronization, you also need to consider what does the code is doing. If one thread is reading and the other is writing then you definitely need some sort of synchronization to achieve the output you want.
Suppose you have the following code:
while(!closed){ printf("Yes, losing weigth is possible"); }
Now, this closed is a boolean field, which may be set by one thread, when the user presses a button and read by another thread that is running this loop. In this case, you need some sort of synchronization so that changes made by one thread are visible to others.
You can achieve that synchronization by using either synchronized or volatile keywords in Java. In fact, it is the right case of using the volatile field, which provides low-cost synchronization.
Now, there are cases, where even though multiple threads execute the code but you don't need any synchronization e.g. reading from HashMap once it is safely initialized. Reading value is a safe operation and can be done without synchronization. provided the value you are reading is not going to change once initialized like final variables.
So, don't say in an interview that if a code is executed by multiple threads then you need synchronization, you also need to consider what does the code is doing. If one thread is reading and the other is writing then you definitely need some sort of synchronization to achieve the output you want.
2. When to use the wait and notify method in Java?
The wait(), notify(), and notifyAll() methods are tools for inter-thread communication in Java. Another set of similar tools is the await(), signal(), and signalAll() from Java 5 which work with Lock and Condition objects.
You need this tool when your program has multiple threads and they need to communicate with each other. The best example of this is again the producer-consumer problem, where two threads need to communicate with each other about their actions because that may affect others.
For example, if the shared queue is empty and the consumer is waiting ( you can use the wait() method or condition.await() in Java 5 to make a thread wait on a condition) for an item in the queue, the producer can notify consumer after successful insertion. Once the consumer receives that notification he can start his job again. You can further see these Java Multithreading courses to learn more about synchronization in Java.
And, if you want to learn more, you can see here to learn more about how to solve the producer-consumer problem using wait and notify in Java.
For example, if the shared queue is empty and the consumer is waiting ( you can use the wait() method or condition.await() in Java 5 to make a thread wait on a condition) for an item in the queue, the producer can notify consumer after successful insertion. Once the consumer receives that notification he can start his job again. You can further see these Java Multithreading courses to learn more about synchronization in Java.
And, if you want to learn more, you can see here to learn more about how to solve the producer-consumer problem using wait and notify in Java.
3. What is the difference between notify and notifyAll in Java?
Before I answer this question, I have general advice for you, always pay attention to the name, more often than not it reveals the purpose. As the name suggests, the notify() method sends notification only to one of the many threads waiting on a condition, while notifyAll() sends the notification to all of them.
Now, in the case of notify() which thread will get the notification? Well, a random thread is chosen. This is also one of the tricky multithreading questions and you may get lots of follow-ups, so make sure you answer it correctly, as you will see in the next question.
Now, in the case of notify() which thread will get the notification? Well, a random thread is chosen. This is also one of the tricky multithreading questions and you may get lots of follow-ups, so make sure you answer it correctly, as you will see in the next question.
4. Why using notifyAll is a safer option than the notify method?
If for some reason, the random thread that receives notification from the notify() method is not able to proceed and starts waiting again, then your program will not progress further. Your application may result in complete deadlock if the thread which calls notify() goes into waiting for state after sending a notification because then there is no active thread to notify all waiting threads.
That's why notifyAll() is a safer option than notify() because it sends a notification to all the threads. If one is not able to proceed, there are still some more threads to do the job. See here to learn more about the difference between notify and notifyAll methods in Java.
This code is inspired by the bank example given in Core Java Volume 1 by Cay S. Horstmann, one of the best books to learn Java. It's a common case of a non-atomic operation that should happen together.
That's why notifyAll() is a safer option than notify() because it sends a notification to all the threads. If one is not able to proceed, there are still some more threads to do the job. See here to learn more about the difference between notify and notifyAll methods in Java.
5. What is wrong with this code in a multi-threading environment in Java?
if(account.getBallance() >= withdrawl ){ double ballance = account.getBallance() - withdrawl; account.setBallance(ballance); }
This code is inspired by the bank example given in Core Java Volume 1 by Cay S. Horstmann, one of the best books to learn Java. It's a common case of a non-atomic operation that should happen together.
If multiple threads execute this code then it's possible that one thread got deactivate after testing the condition like sufficient balance in the account, but when it got up and start again, the situation might have changed by another thread by processing another withdrawal operation and now there is not enough fund to complete this transaction.
In order to make this code thread-safe and correct, you must wrap both test and transaction inside a synchronized block as shown below:
If you are using Java 5 and knows how to use the java.util.concurrent.lock.Lock interface then you can also use a ReentrantLock to protect this code. This is also known as the critical section, a code segment that should only be executed by one thread at a time.
In order to make this code thread-safe and correct, you must wrap both test and transaction inside a synchronized block as shown below:
// member variable in class Object accountLock = new Object(); sychronized(accountLock){ if(account.getBallance() > withdrawl ){ double ballance = account.getBallance() - withdrawl; account.setBallance(ballance); } }
If you are using Java 5 and knows how to use the java.util.concurrent.lock.Lock interface then you can also use a ReentrantLock to protect this code. This is also known as the critical section, a code segment that should only be executed by one thread at a time.
6. Can a thread enter a synchronized block without acquiring a lock-in Java?
No, it's not possible. A thread must acquire the lock required by a synchronized block before entering. The synchronized keyword acquires the lock when a Thread enters and releases the lock Thread leaves the block. Since there can be only one lock and if it is used by another thread then this thread needs to wait until the lock is available.
Now there can be many gotchas, sometimes Java programmer uses different locks to protect the same resource, which is plain wrong. It's like two doors in your bathroom with separate locks and keys. You don't want someone to see you when you are inside the toilet right?
So, you must use the same lock object or mutex to protect the same resources, if you have to use multiple locks then use multi-level locks i.e. you open the house door then you open the toilet door, so you need both houses and toilet keys to use the toilet.
Now there can be many gotchas, sometimes Java programmer uses different locks to protect the same resource, which is plain wrong. It's like two doors in your bathroom with separate locks and keys. You don't want someone to see you when you are inside the toilet right?
So, you must use the same lock object or mutex to protect the same resources, if you have to use multiple locks then use multi-level locks i.e. you open the house door then you open the toilet door, so you need both houses and toilet keys to use the toilet.
7. What happens to the thread after calling the wait() method? Does it return lock?
This is one of the most interesting questions on this topic. I have seen many programmers confuse themselves when asked during interviews, how come the other thread got lock when the first thread stuck after calling wait()?
Well, when a thread sees that condition to proceed further is not ok, it decides to wait by calling the wait() method, but it does release the lock. Yes, this is really important, a thread is not proceeding further but the lock is released so that other threads waiting for the lock can proceed.
Well, when a thread sees that condition to proceed further is not ok, it decides to wait by calling the wait() method, but it does release the lock. Yes, this is really important, a thread is not proceeding further but the lock is released so that other threads waiting for the lock can proceed.
This is also the key difference between the sleep() and the wait() method, which is used to pause a thread (see here)
8. What happens to the waiting thread (who has called wait() method) once another thread calls notifyAll()?
When a thread calls the notifyAll() or signalAll() method, all threads waiting on that condition (a condition associated with lock and notifyAll() is called on an object, which holds the lock) gets a notification.
Now they are free from waiting for the state but they still need CPU to be allocated by the thread scheduler to proceed further. When they get their chances, they proceed further. See here to learn more about the wait, notify, and notifyAll methods in Java.
9. What is the difference between a thread waiting for the lock and waiting after calling the wait() method?
A thread waiting for lock gets activated (become eligible to run again) once a lock is free and acquired by this lock and CPU is allocated to it. A thread waiting on condition may not be runnable again even if the lock is free but he hasn't received any notification from another thread e.g. until someone call notify() or notifyAll() in the case of wait() and signal() or signalAll() in the case of waiting on a Condition object.
I have already answered this question in good detail, please read this article to understand the risk and dangers of calling wait and notify without any synchronized context.
If you can answer these questions correctly and confidently without confusing yourself, then you are in good safe, otherwise, it's time to read the Effective Java and Java Concurrency in Practice again
If you can answer these questions correctly and confidently without confusing yourself, then you are in good safe, otherwise, it's time to read the Effective Java and Java Concurrency in Practice again
11. Why you should check waiting conditions on the while loop instead of if block?
One of the interesting and practical questions. You need to check the waiting condition in the loop because it's possible that even after a wake-up call by notify() the waiting condition still holds. If a thread doesn't check the waiting condition after wake up, it might do harm by proceeding further.
This could be due to many reasons e.g. more than one thread waiting on that condition and until the second thread gets a chance, the first has already proceeded and nullified that wake-up call.
For example, if 3 consumers are waiting and a producer puts one item in the queue and notify all three, The first consumer will get the item and the other two needs to wait. This is only possible when you check the condition in the while() loop.
Btw, that's also the standard idiom to use wait() and notify() as suggested by Joshua Bloch in Effective Java.
That's all about some Java interview questions on wait() and notify(), locking, synchronization, and inter-thread communication. I know, it's one of the tricky concepts to understand and master and that's why I have asked tricky questions. Once you are comfortable answering this question, your understanding of wait() and notify() will become solid.
Keep writing code and thinking about what happens if the same code block is run by multiple threads at the same time. Remember, Thread can stop at any line, and the only line of code may be composed of multiple instructions e.g. ++ or != are not atomic.
I also suggest reading Java Concurrency in Practice from start to end for at least one time. It will help you to fill gaps in your existing knowledge of multithreading, synchronization, and concurrency in Java.
Other Java Multi-threading Interview Questions you may like to explore
Thanks for reading this article. If you like this post then please share it with your friends and colleagues. If you have any suggestions or feedback then please drop a comment. Btw, if you think that Java Concurrency in Practice is not relevant in the era of Java 8, then please read this article before making your judgment.
This could be due to many reasons e.g. more than one thread waiting on that condition and until the second thread gets a chance, the first has already proceeded and nullified that wake-up call.
For example, if 3 consumers are waiting and a producer puts one item in the queue and notify all three, The first consumer will get the item and the other two needs to wait. This is only possible when you check the condition in the while() loop.
Btw, that's also the standard idiom to use wait() and notify() as suggested by Joshua Bloch in Effective Java.
12. Why wait and notify methods are defined in java.lang.Object class instead of Thread?
The short answer is because Object is also a monitor in Java. It comes with an associated lock and the wait(), notify() are associated with waiting for the condition on lock so it makes sense to define them in the java.lang.Object. For the long answer, see this article.That's all about some Java interview questions on wait() and notify(), locking, synchronization, and inter-thread communication. I know, it's one of the tricky concepts to understand and master and that's why I have asked tricky questions. Once you are comfortable answering this question, your understanding of wait() and notify() will become solid.
Keep writing code and thinking about what happens if the same code block is run by multiple threads at the same time. Remember, Thread can stop at any line, and the only line of code may be composed of multiple instructions e.g. ++ or != are not atomic.
I also suggest reading Java Concurrency in Practice from start to end for at least one time. It will help you to fill gaps in your existing knowledge of multithreading, synchronization, and concurrency in Java.
Other Java Multi-threading Interview Questions you may like to explore
- Top 50 Java Thread Interview Questions with Answers (list)
- Top 5 Courses to learn Multithreading and Concurrency in Java (courses)
- Top 12 Java Concurrency Questions for Experienced Programmers (see here)
- Top 5 Books to learn Java Concurrency in-depth (books)
- Top 15 Multithreading and Concurrency Questions from Investment banks (see here)
- 133 Core Java Interview Questions from the last 5 years (see here)
- How volatile variable works in Java? (answer)
- Top 10 Java Concurrency and multi-threading best practices (article)
- Difference between start() and run() method in Java? (answer)
- Top 10 Courses to learn Java in-depth (courses)
- 10 Courses to Crack Java Interviews for Beginners (courses)
- Top 5 courses to Learn Java Performance Tuning (courses)
- What is happens-before in Java Concurrency? (answer)
- 6 Books to learn Multithreading and Concurrency in Java (books)
- 10 Advanced Core Java Courses for Experienced programmers (course)
Thanks for reading this article. If you like this post then please share it with your friends and colleagues. If you have any suggestions or feedback then please drop a comment. Btw, if you think that Java Concurrency in Practice is not relevant in the era of Java 8, then please read this article before making your judgment.
P. S. - If you are a Java beginner and want to learn multithreading and concurrency and looking for some free courses to start with then you can also check out this free Java Multithreading course on Udemy. It is a good free course to learn Java Concurrency as well.
And, Lastly one question for you, Which multithreading and concurrency questions were asked on your last Java interview?
Good article.
ReplyDelete