看代码:
public class TestDeadLock implements Runnable{ int flag = 1; static Object o1 = new Object(); //资源1,也称为锁 static Object o2 = new Object(); //资源2,也称为锁 public static void main(String[] args) { TestDeadLock td1 = new TestDeadLock(); TestDeadLock td2 = new TestDeadLock(); td1.flag = 1; td2.flag = 0; Thread t1 = new Thread(td1); Thread t2 = new Thread(td2); t1.start(); t2.start(); } //锁,是个对象,给谁上锁,是给synchronized语句中的代码上锁, public void run() { if(flag == 1){ synchronized(o1) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized(o2){ System.out.println("t1 succeed"); } } } if(flag == 0){ synchronized(o2){ try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized(o1){ System.out.println("t2 succeed"); } } } } }
(1)线程t1(td1)就相当于一个人。
(2)对象o1就相当于一把锁。锁也可称为独占资源。
(3)synchronized(o1)就相当于屋里的财富。
当线程t1运行到synchronized(o1)中,就相当于这个人走进了屋里,同时把屋的门给锁定(即o1锁定),当线程t1走出synchronized(o1)的代码段后,就相当于这个人走出了屋,同时把锁释放掉,别人(如t2)就可以拥有锁,可以进屋。
我们来看上端代码,t1和t2两个线程,假设首先t1进入run()方法,然后判断flag是否为1,为1则利用对象o1将下面那段代码锁住,与此同时t2进入run()方法,判断flag,为0,则利用o2将下面那段代码锁住,再回过头来,此时t1继续向下执行,执行到synchronized(o2)这,此时o2对象已经被t2锁住,所以o1开始等待o2对象释放锁标记,同理,t2继续往下执行,执行到synchronized(o1)这,也就开始等待o1对象释放锁标记.这样互相等待,就产生死锁.
注意:如果我把static Object o1 = new Object();前面的static去掉的话,那么就不会发生死锁了,这是因为,这两个线程都有自己的o1,即锁不再是公用的了,所以不会发生死锁了.