Linux下死锁

2016-11-09  本文已影响0人  34a43ac295b8

产生死锁的代码

//Deadlock.java
class A{
synchronized void methodA(B b){
    b.last();
}
synchronized void last(){
    System.out.println("Inside A.last()");
}
}
class B{
synchronized void methodB(A a){
    a.last();
}
synchronized void last(){
    System.out.println("Inside B.last()");
}
}

class Deadlock implements Runnable{
A a = new A();
B b = new B();
Deadlock(){
    Thread t = new Thread(this);
    int count=200000;
    t.start();
    while(count-- >0);
    a.methodA(b);
}
public void run(){
    b.methodB(a);
}
public static void main(String args[]){
    new Deadlock();
}
}

之后用预处理文件Deadlock.bat运行
#!/bin/bash
for((c=1;c<=300;c++))
do
echo "$c times"
java Deadlock
done
注:linux下运行bat文件:

  1. chmod +x 文件名
    先用上面的命令把批处理文件修改为可执行文件。
  2. ./文件名
    执行该文件。

运行结果

blocked in the 154th iterations.png

如果发现没有死锁,可以把每个锁占有时间count延长,或者加大迭代次数c。

产生死锁的必要条件

代码分析

首先是synchronized 关键字,使用这个关键字来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。当一个线程访问object的一个synchronized同步代码块或同步方法时,其他线程对object中所有其它synchronized同步代码块或同步方法的访问将被阻塞。

这样使得两个类的last函数相当于一个资源锁,不能同时被并行访问。
在主函数中新建一个deadlock对象,这个对象的构造函数中会建一个线程,当线程调用start()函数时,会运行run()函数,run函数中使得b占用a的锁,然后释放。接着回到t.start()的下一步,在设置的count毫秒内使得a占有b的锁。

使用预处理文件循环跑这个代码,使得有可能出现下面的情况:
b.methodB(a)的同时a.methodA(b),在这两个函数内部调用的是对方的last函数,但是由于synchronized 关键字使得只能有一个线程访问对象的一个synchronized函数,其他的被阻塞,所以造成了:a调用自己的methodA函数,使得自己的last函数被阻塞,b也一样,这样a和b同时在等待对方的last函数,导致死锁。

上一篇 下一篇

猜你喜欢

热点阅读