Thursday, November 19, 2020

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 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 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.

By the way, if you are serious about mastering Java multi-threading and concurrency then I also suggest you take a look at the Java Multithreading, Concurrency, and Performance Optimization course by Michael Pogrebinsy on Udemy.  It's an advanced course to become an expert in Multithreading, concurrency, and Parallel programming in Java with a strong emphasis on high performance.

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 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:

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 are visible to others.



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 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 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 the producer-consumer problem using wait and notify in Java.
Java wait, notify, locking and synchronization interview Questions Answers



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.



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.

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.



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 which 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.

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 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 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 house and toilet keys to use the toilet.


Top 10 Java Synchronization interview questions



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. 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 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 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.


Top 10 Java wait, notify, and notifyAll Interview Questions




10. Why wait() method should be called from a 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.

 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 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, 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 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 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.

Further Learning
Multithreading and Parallel Computing in Java
Applying Concurrency and Multi-threading to Common Java Patterns
Java Concurrency in Practice Course by Heinz Kabutz


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.

1 comment :

Post a Comment