在学习操作系统时,已经反复理解很多遍了,所以我们直接给出死锁的例子:
一个经典的小品《不差钱》
赵本山:“你先上菜再唱”
小沈阳:“你不让我唱我就不给你上菜”
这不就是经典的死锁吗。
public class DeadLock {
public static void main(String[] args) {
ServerDinner serverDinner = new ServerDinner(); //上菜的权利只有一份,这很重要!
CanSing canSing = new CanSing(); //唱歌的权利只有一份,这很重要!
//赵本山:拥有让小沈阳唱歌的权利,还想要上菜
ZhaoBenShan zhaoBenShan = new ZhaoBenShan(serverDinner,canSing);
zhaoBenShan.start();
//小沈阳:拿着上菜的权利,还想要唱歌的权利
XiaoShenYang xiaoShenYang = new XiaoShenYang(serverDinner,canSing);
xiaoShenYang.start();
}
}
//上菜的权利
class ServerDinner{ }
//唱歌的权利
class CanSing{}
//小沈阳:拿着上菜的权利,还想要唱歌的权利
class XiaoShenYang extends Thread{
ServerDinner serverDinner;
CanSing canSing;
public XiaoShenYang(ServerDinner serverDinner,CanSing canSing){
this.serverDinner = serverDinner;
this.canSing = canSing;
}
@Override
public void run() {
synchronized (serverDinner){
System.out.println("小沈阳:你不让我唱歌我就不给你上菜");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (canSing){
System.out.println("小沈阳:成功唱歌");
}
}
}
}
//赵本山:拥有让小沈阳唱歌的权利,还想要上菜
class ZhaoBenShan extends Thread{
ServerDinner serverDinner;
CanSing canSing;
public ZhaoBenShan(ServerDinner serverDinner,CanSing canSing){
this.serverDinner = serverDinner;
this.canSing = canSing;
}
@Override
public void run() {
synchronized (canSing){
System.out.println("赵本山:先上菜再唱歌");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (serverDinner){
System.out.println("赵本山:成功得到菜");
}
}
}
}
运行结果:
注意,唱歌的权利和上菜的权利只能有一份。如果唱歌或者上菜的权利有两份,那么就不会产生死锁了。
如何避免(不知道这里“避免”用的对不对哈)死锁?
对于小沈阳,把 synchronized (canSing) 的代码段拿出来从 synchronized (serverDinner)中拿出来 。也就意味着让出上菜的权利之后,再去索要唱歌的权利。
对于赵本山,同样的道理。先让出唱歌的权利,再索要上菜的权利。
收获:
在模拟Rip协议的项目中,自己处理完几个死锁问题,就彻底明白了如何分析,解决死锁。所以,光学习只有输入不行,必须有项目实战作为输出!