About NewTechnoBuzz
Advertise
Contact Us

Friday, July 18, 2014

How to avoid deadlock in Java Threads

In general, you should synchronization in Java whenever you are reading any variable that can be accessed by a different thread. Additionally, while synchronization carries a performance penalty, the penalty associated with unintended synchronization is not as great as some sources have suggested, and has reduced steadily with each successive JVM implementation. So it seems that there is now less reason than ever to avoid synchronizing. However, another risk is associated with excessive synchronization: deadlock.

What is deadlock

Deadlock is a programming situation where two or more threads are blocked forever. This situation arises with at least two threads and two or more resources.
The following example shows a set of methods that will cause a deadlock scenario. Both methods acquire locks on two lock objects, object1 and object2 , before they proceed. In this example, the objects acting as locks are global (static) variables, a common technique for simplifying application-locking behavior by performing locking at a coarser level of granularity:

  public static Object object1 = new Object();
  public static Object object2 = new Object();

  public void oneMethod() {
    synchronized (object1) {
      synchronized (object2) { 
        doSomething();
      }
    }
  }
  public void anotherMethod() {
    synchronized (object2) {
      synchronized (object1) { 
        doSomethingElse();
      }
    }
}

Testing for deadlocks is difficult, as deadlocks depend on timing, load, and environment, and thus might happen infrequently or only under certain circumstances. Code can have the potential for deadlock, like Listing 1, but not exhibit deadlock until some combination of random and nonrandom events occur, such as the program being subjected to a certain load level, run on a certain hardware configuration, or exposed to a certain mix of user actions and environmental conditions.

Deadlock Prevention

Below are some of the guidelines which can be used to avoid most of the deadlock situations.
  • Avoid Nested Locks - This is the one of the most common reason for deadlocks, avoid locking another resource if you already hold any resource. It’s almost impossible to get deadlock situation if you work only with one object lock at a time. For example, here is the implementation of run() method without nested lock and program runs successfully without deadlock situation.
public void run() {
    String threadName = Thread.currentThread().getName();
    System.out.println(threadName + " acquiring lock on " + object1);
    synchronized(object1) {
        System.out.println(threadName + " acquired lock on " + object1);
    }
    System.out.println(threadName + " released lock on " + object1);
    System.out.println(threadName + " acquiring lock on " + object2);
    synchronized(object2) {
        System.out.println(threadName + " acquired lock on " + object2);
    }
    System.out.println(threadName + " released lock on " + object2);
 
    System.out.println(threadName + " finished.");
}
  • Lock Only What is Required - You should acquire lock only on the resources you have to work on, for example in above program I am locking the complete Object resource but if we are only interested in one of it’s fields, then we should lock only that specific field not complete object.
  • Lock Timeout - You can get deadlock if two threads are waiting for each other to finish indefinitely using thread join. If your thread has to wait for another thread to finish, it’s always best to use join with maximum time you want to wait for thread to finish.
I hope that you understand the article. If you find any difficulty, then please provide your valuable comments and feedback to improve article.

0 comments