Top 10 Java wait, notify, Locking and Synchronization Interview Questions

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 basics of inter-thread communication, synchronization, locking and understand how all the things work together. They should be able to reason the output of 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 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 some interview questions to check and challenge your understanding. If you can answer these question correct 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.




10 Locking, Synchronization, and Inter-Thread Communication Questions in Java

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 then without any difficulty.


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 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 which is running this loop. In this case, you need some sort of synchronization so that changes made by one thread is visible to other.



You can achieve that synchronization by using either synchronized or volatile keyword 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 e.g. final variables.

So, don't say in an interview that if a code is executed by multiple threads then you need synchronization, you also needs to consider what does the code is doing. If one thread is reading and other is writing then you definitely need some sort of synchronization to achieve the output you want.


When to use 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 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. See here to learn more about how to solve producer consumer problem using wait and notify in Java.
Java wait, notify, locking and synchronization interview Questions Answers


What is the difference between notify and notifyAll in Java?
Before I answer this question, I have a general advice for you, always pay attention to the name, more often than not it reveal the purpose. As the name suggests, the notify()  method send notification only to one of the many threads waiting on a condition, while notifyAll() send 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 next question.


Why using notifyAll is a safer option than the notify method?
If for some reason, the random thread who 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.

Java  locking and synchronization interview Questions

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 is still some more threads to do the job. See here to learn more about the difference between notify and notifyAll methods in Java.



What is wrong with this code in multi-threading environment in Java?
if(account.getBallance() >= withdrawl ){
  double ballance = account.getBallance() - withdrawl;
  account.setBallance(ballance);
}

This code is inspired by 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 which should happen together. If multiple threads execute this code then it's possible that one thread got deactivate after testing the condition i.e. 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.

Top 10 Java wait, notify, locking and synchronization interview Questions


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 which should only be executed by one thread at a time.


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 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 than 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 same lock object or mutex to protect same resources, if you have to use multiple locks then use multi-level locks i.e. you open house door then you open toilet door, so you need both house and toilet keys to use the toilet.

Top 10 Java Synchronization interview questions


What happens to the thread after calling 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 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. This is also the key difference between the sleep() and the wait() method, which is used to pause a thread (see here)


What happens to the waiting thread (who have called wait() method) once another thread calls notifyAll()?
When a thread calls the notifyAll() or signalAll() method, all thread 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 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.


What is the difference between a thread waiting for the lock and waiting after calling 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.

Top 10 Java wait, notify, and notifyAll Interview Questions




Why wait() method should be called from synchronized method or block? 
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.


Why you should check waiting condition on while loop instead of if block?
One of the interesting and Practical question. 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, 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 other two needs to wait. This is only possible when you check the condition in while() loop.

Btw, that's also the standard idiom to use wait() and notify() as suggested by Joshua Bloch in Effective Java.



Why wait and notify method 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 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 multi-threading, 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 12 Java Concurrency Questions for Experienced Programmers (see here)
  • Top 15 Multithreading and Concurrency Questions from Investment banks (see here)
  • 133 Core Java Interview Questions from 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)

Thanks for reading this article. If you like this post then please share with your friends and colleagues. If you have any suggestion 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. 


No comments :

Post a Comment