DistributedAI
DistributedAI

Reputation: 193

Why deadlock is occuring intermittently in my code?

Below code I have written for a deadlock, but for small "for loop" code is not falling in deadlock while when I keep "for loop" till 10 then deadlock is occurring.

Can someone plz explain, why it is showing such behavior ?

public class CustomerUpdateDeadloackThread {

    public static void main(String[] args) {

        Customer cstmr = new Customer("Peter");
        Address adrs = new Address("B-232, Bangalore");


    // For loop till 3 is not showing deadlock.
    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 (this) {
            synchronized ((Customer) cstmr) {
                try {
                    this.customer = (Customer) cstmr;
                    Thread.sleep(2000); // or else do some other work here
                } 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) {
                try {
                    this.address = (Address) adrs;
                    Thread.sleep(2000); // or else do some other work here
                } 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";
    }

}

Upvotes: 2

Views: 265

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499770

You're only going to get a deadlock if one of your threads obtains one monitor and the other thread obtains the other monitor before the first thread obtains the second monitor. The more threads you have obtaining the monitors on the two objects, the more likely it is that one of them will obtain just one lock and be pre-empted before it gets a chance to obtain the second monitor.

In other words, this is fine, and just causes a wait:

  Thread A               Thread B
  Lock X
  Lock Y
                         Lock Y // Blocks (temporary)
  Sleep
                         Lock X
                         Sleep

Whereas this causes deadlock:

  Thread A               Thread B
  Lock X
                         Lock Y
  Lock Y // Blocks (deadlock)
                         Lock X // Blocks (deadlock)

If you move your Thread.sleep(2000) call to between your two synchronized statements (in both methods) then you're almost guaranteed to get a deadlock, without any looping at the top level.

Upvotes: 6

Related Questions