Today’s post is on breaking Deadlock of multiple Threads : on “November 5, 2014” I had posted a code of creating Deadlock.
Today I am modifying the same code for avoiding such Deadlock. There are many ways to avoid a deadlock but simple rule is: have all threads claim and release their locks in the same order. In this way, you never get into a situation where a deadlock can occur.
My updated code without Deadlock
========================================
public class CustomerUpdateDeadloackThread { public static void main(String[] args) { Customer cstmr = new Customer("Peter"); Address adrs = new Address("B-232, Bangalore"); for (int i = 0; i < 10; i++) { new Thread(new TagObjectsToEachOther(cstmr, adrs)).start(); new Thread(new TagObjectsToEachOther(adrs, cstmr)).start(); } } } interface CustomerUpdater { public boolean update(Object obj); } class TagObjectsToEachOther implements Runnable { CustomerUpdater taskItem; Object objToUpdateWith; public TagObjectsToEachOther(CustomerUpdater cspdtr, Object obj2) { this.taskItem = cspdtr; this.objToUpdateWith = obj2; } @Override public void run() { taskItem.update(objToUpdateWith); System.out.println(" Task done :" + Thread.currentThread().getName()); } } class Address implements CustomerUpdater { String address; Customer customer; public Address(String addrs) { this.address = addrs; } @Override public boolean update(Object cstmr) { synchronized ((Customer) cstmr) { // same order of locks will be used at other places !!! synchronized (this) { try { this.customer = (Customer) cstmr; Thread.sleep(2000); // or else do some other work here so that lock gets used for some more time } catch (CustomerUpdateFailureException e) { e.getCause(); return false; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return true; } } } } class Customer implements CustomerUpdater { String name; Address address; public Customer(String nm) { this.name = nm; } @Override public boolean update(Object adrs) { synchronized (this) { synchronized ((Address) adrs) { // Maintaining order of accessing lock to avoid deadlock !!! try { this.address = (Address) adrs; Thread.sleep(2000); // or else do some other work here so that lock gets used for some more time } catch (CustomerUpdateFailureException e) { e.getCause(); return false; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return true; } } } } class CustomerUpdateFailureException extends RuntimeException { private static final long serialVersionUID = 1L; @Override public String getMessage() { return "Uncompitable update"; } } =================== Output ========================= Task done :Thread-0 Task done :Thread-9 Task done :Thread-8 Task done :Thread-7 Task done :Thread-6 Task done :Thread-5 Task done :Thread-4 Task done :Thread-3 Task done :Thread-2 Task done :Thread-1