关于“死锁”,《JAVA开发实战经典》一书上有个例子,我小改了一下,感觉这样容易理解些,这样的思路是否正确?运行结果是一样的。
class ZhangSan
{
public void say(){
System.out.println("张三对李四说:“你给我画,我就把书给你。”");
}
public void get(){
System.out.println("张三得到画了。");
}
public void give(){
System.out.println("张三把书给李四了。");
}
};
class LiSi
{
public void say(){
System.out.println("李四对张三说:“你给我书,我就把画给你。”");
}
public void get(){
System.out.println("李四得到书了。");
}
public void give(){
System.out.println("李四把画给张三了。");
}
};
class Exchange implements Runnable
{
private ZhangSan zs;
private LiSi ls;
private boolean flag;
public Exchange(ZhangSan zs,LiSi ls,boolean flag){
this.zs = zs;
this.ls = ls;
this.flag = flag;
}
public void run(){
if (this.flag)
{
synchronized(zs){
zs.say();
synchronized(ls){
try{
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
ls.give();
}
zs.get();
try{
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
zs.give();
}
}else{
synchronized(ls){
ls.say();
synchronized(zs){
try{
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
zs.give();
}
ls.get();
try{
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
ls.give();
}
}
}
};
public class ThreadDeadLock
{
public static void main(String args[]){
ZhangSan zs = new ZhangSan();
LiSi ls = new LiSi();
Exchange e1 = new Exchange(zs,ls,true);
Exchange e2 = new Exchange(zs,ls,false);
new Thread(e1).start();
new Thread(e2).start();
}
};
你这样写虽然运行结果是对的,但是你错误的理解加Thread.sleep(500)的意义了,你的意思可能是要等5毫秒才能把书给我
而且这个sleep并没有起任何作用,为什么运行结果会一样,因为代码没有运行到这个同步快里面来,书中加sleep只是模拟让死锁更能重现出来,不加的话就有可能张三刚开始对李四说你给我画,我把书给你,张三就已经得到画了,而这时李四才刚开始说
你要明白synchronized(obj){}的作用,就是必须等这个obj在其他的线程的同步操作执行完,才能执行里面同步块的操作,而书中为什么会有死锁,是因为当flag为false时,执行到synchronized(zs){}时,而zs被flag为true时同步着还没执行完,同样的flag为true时,执行到synchronized(ls){}时,而ls被flag为false时同步着还没执行完