看代码:
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,即锁不再是公用的了,所以不会发生死锁了.