为什么在我的代码中间歇性地发生死锁?

时间:2014-11-04 17:25:49

标签: java multithreading

下面的代码我写了一个死锁,但是对于小的“for循环”代码并没有陷入死锁,而当我保持“for循环”直到10时,就会发生死锁。

有人可以解释,为什么会出现这种行为?

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";
    }

}

1 个答案:

答案 0 :(得分:6)

如果你的一个线程获得一个监视器并且另一个线程在第一个线程获得第二个监视器之前获得另一个监视器,那么你只会遇到死锁。你在两个对象上获得监视器的线程越多,它们中的一个就越有可能只获得一个锁并在它有机会获得第二个监视器之前被抢占。

换句话说,这很好,只会导致等待:

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

这导致死锁:

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

如果您将Thread.sleep(2000)调用移到两个synchronized语句之间(在这两种方法中),那么几乎可以保证在没有任何循环的情况下出现死锁顶级。

相关问题