Deadlock in Java – wait, notify & notifyAll

Deadlock is a part of multithreading in Java. Suppose there is a thread waiting for a lock of an object which is currently acquired by another thread and the second thread is waiting for a lock on an object that is currently acquired by the first thread. Deadlock appears in this situation. This case is known as deadlock because both the threads are waiting for each other to release the object’s lock.

Inter-thread communication in Java

The definition of inter-thread communication is the communication between synchronized threads in the Java. It is also known as co-operation. It is the process in which one thread that is currently running is paused in its critical section and another thread is allowed to lock in the same critical section and is executed. The inter-thread communication is implemented by the methods of the object class mentioned below:

1. wait() method

The wait() method is used to make the current thread release the lock and make it wait until another thread calls on the notify() method or the notifyAll() method for the object or for a specific amount of time. It can only be invoked from the synchronized method because the current thread should own this object’s monitor. If not, the method with throw an exception. The following are the syntaxes of the wait() method:

synchronized( // lockObject )
{
    while( // condition )
    {
        lockObject.wait();
    }
    // action;
}
  • public final void wait():

This method causes the current thread to wait until the object is notified.

  • public final void wait(long timeout):

This method causes the current thread to wait for a particular amount of time.

2. notify() method

The notify() method is used to wake up a single thread that was paused by using the wait() method. One of the threads that are waiting on the object’s lock is selected arbitrarily and awakened using this method. The following is the syntax of the notify() method:

synchronized(lockObject)
{
    // condition
 
    lockObject.notify();
     
   }
  • public final void notify()

Here is a simple example of wait and notify methods:

public class Customer {
	int amount = 3000;
	synchronized void withdraw(int amount) {
		System.out.println("Going to withdraw: ");
		if (this.amount < amount)
			System.out.println("Less balance wait for deposit..");

		try {
			wait(); // <----
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.amount -= amount;
		System.out.println("Withdraw completed...");
	}
	synchronized void deposit(int amount) {
		System.out.println("Going to deposit...");
		this.amount += amount;
		System.out.println("Deposit is completed...");
		notify(); // <---- 
	}
}
public class Test {

	public static void main(String[] args) {

		Customer c = new Customer();
		new Thread() {
			public void run() {

				c.withdraw(5000);
			}
		}.start();

		new Thread() {
			public void run() {

				c.deposit(5000);
			}
		}.start();
	}
}

3. notifyAll() method

The notifyAll() method wakes up all the threads that were paused by using the wait() method and are waiting on the object’s lock. The following is the syntax of this method:

synchronized(lockObject)
{
     // condition
 
    lockObject.notifyAll();
}
  • public final void notifyAll() 

Understanding the process of inter-thread communication

The following are the main points needed to understand the process of inter-thread communication:

  1. In the first step, threads enter to acquire an object’s monitor.
  2. The thread then acquires the monitor.
  3. If the programmer invokes the wait() method, the thread is paused. Otherwise, it will release the monitor and exit.
  4. When the programmer invokes the notify() method or the notifyAll() method, the thread that is paused will move to the runnable state.
  5. The thread again becomes available to acquire monitor.
  6. After the thread completes its task, it releases the monitor and exits.

Why are these methods defined in object class rather than in the thread class?

The wait(), notify(), and notifyAll() methods are defined in object class and not in the thread class because these methods are related to lock or monitor and the objects have the lock.

Dissimilarities between wait and sleep method

There are various dissimilarities between the wait and the sleep method and they are:

  1. The wait method releases the lock but the sleep method does not.
  2. The wait method is of object class but the sleep method is of the thread class.
  3. The wait method is a non-static method. Whereas, the sleep method is a static one.
  4. The thread becomes active after the wait method has been called by invoking the notify method or the notifyAll method. However, the thread becomes active after a specified amount of time when the sleep method is invoked to make them sleep.
public class DeadLockDemo {

	public static void main(String[] args) {
		final String name1 = "John";
		final String name2 = "Alex";

		Thread t1 = new Thread() {
			public void run() {
				synchronized (name1) {
					System.out.println("Thread1 locked with name1...");
					try {
						Thread.sleep(1000); // <------
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					synchronized (name2) {
						System.out.println("Thread1 locked with name2...");
					}
				}
			}
		};
		Thread t2 = new Thread() {
			public void run() {
				synchronized (name2) {
					System.out.println("Thread2 locked with name2...");
					try {
						Thread.sleep(1000); // <--------
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					synchronized (name1) {
					System.out.println("Thread2 locked with name1...");
					}
				}
			}
		};
		t1.start();
		t2.start();
	}
}

Interrupting a thread

The interrupt() method is used to break put the sleeping or the waiting state of the threads that are in those states after the sleep() method or the wait() method had been invoked on them. This method does so by throwing an InterruptedException and performs normal behavior if it has been invoked while a thread is not in a waiting or in a sleeping state. In this situation, the method sets the interrupt flag to true but does not actually interrupt the thread. Let’s first deal with the methods that are provided by the thread class to interrupt a thread.

Methods provided by the thread class to interrupt a thread

There are three methods that are used to interrupt a thread and they are:

  • public void interrupt():

This method is used to interrupt a thread from the waiting or the sleeping state.

  • public static boolean interrupted():

This method returns true if the static thread has been interrupted otherwise returns false.

  • public boolean isInterrupted():

This method returns true if the thread has been interrupted otherwise returns false.

Reentrant Monitor in Java

The Sun Microsystems defines the Java monitors as a reentrant. This means that a thread can reuse the same monitor for different synchronized methods in the case in which the method is called from the method.

The benefits of reentrant monitor

The reentrant monitor removes the possibility of deadlocking a single thread.

Leave a Reply

Your email address will not be published. Required fields are marked *