java并发之死锁

来源:互联网 发布:java就业培训教程 pdf 编辑:程序博客网 时间:2024/04/20 05:09

上一篇博客 java并发之加锁中主要介绍了在数据库中的加锁问题,现在来聊聊Java中会出现的死锁。
关于死锁,一般教科书的都会罗列满足死锁的几个概念,如互斥、竞态条件等,今天从代码里直接去看死锁,或许会更加直观,直捣黄龙,比记住概念要强得多。

/** * @author Jerry */public class ThreadDeadlock {    public static void main(String[] args) throws InterruptedException {        Object obj1 = new MyObject("lockA");//这里是几个锁,为下面三个线程共同来争取        Object obj2 =  new MyObject("lockB");        Object obj3 = new MyObject("lockC");        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1"); //三个线程,注意三个线程加锁的顺序,会形成闭环        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");        Thread t3 = new Thread(new SyncThread(obj3,obj1), "t3");        t1.start();        Thread.sleep(5000);        t2.start();        Thread.sleep(5000);        t3.start();    }}class MyObject{    private String name;    public MyObject(String name) {        this.name = name;    }    @Override    public String toString() {        return name;    }}class SyncThread implements Runnable{    private Object obj1;    private Object obj2;    public SyncThread(Object o1, Object o2){        this.obj1=o1;        this.obj2=o2;    }    @Override    public void run() {        String name = Thread.currentThread().getName();        System.out.println(name + " acquiring lock on "+obj1);        synchronized (obj1) {            System.out.println(name + " acquired lock on "+obj1);            work();            System.out.println(name + " acquiring lock on "+obj2);            synchronized (obj2) {//要形成死锁,这里的锁获取要形成嵌套,才会让线程既拥有一个锁又想再去获取另一个                System.out.println(name + " acquired lock on "+obj2);                work();            }            System.out.println(name + " released lock on "+obj2);        }        System.out.println(name + " released lock on "+obj1);        System.out.println(name + " finished execution.");    }    private void work() {        try {            Thread.sleep(20000);//模拟耗时操作        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

最后这里运行结果如下,程序不会终止,没有一个线程释放了锁,线程之间在相互等待,形成了死锁阻塞。

t1 acquiring lock on lockAt1 acquired lock on lockAt2 acquiring lock on lockBt2 acquired lock on lockBt3 acquiring lock on lockCt3 acquired lock on lockCt1 acquiring lock on lockBt2 acquiring lock on lockCt3 acquiring lock on lockA

我们如果稍微修改一下代码,将原本 Thread t3 = new Thread(new SyncThread(obj3,obj1), “t3”);
替换成 Thread t3 = new Thread(new SyncThread(obj1,obj3), “t3”);
这样运行的结果如下,可以看出程序不形成死锁,已正常关闭。

t1 acquiring lock on lockAt1 acquired lock on lockAt2 acquiring lock on lockBt2 acquired lock on lockBt3 acquiring lock on lockAt1 acquiring lock on lockBt2 acquiring lock on lockCt2 acquired lock on lockCt2 released lock on lockCt2 released lock on lockBt2 finished execution.t1 acquired lock on lockBt1 released lock on lockBt1 released lock on lockAt1 finished execution.t3 acquired lock on lockAt3 acquiring lock on lockCt3 acquired lock on lockCt3 released lock on lockCt3 released lock on lockAt3 finished execution.

或者我们将锁获取方式由嵌套换成一次获取,也就是每次只是持有一个锁,也会得到如上的结果。

syn(lock1){                         syn(lock1){}    syn(lock2){                     syn(lock2){}    }}   

所以避免死锁可以通过每次只获取一个锁或者依次获取锁来避免死锁的问题,当然也可以通过一些超时设定机制来强制退出,解决死锁问题。

原创粉丝点击