Java中常见死锁的实例

栏目: Java · 发布时间: 5年前

内容简介:运行后输出如下可以通过jstack发现死锁的痕迹可以看到
  • 顺序死锁:过度加锁,导致由于执行顺序的原因,互相持有对方正在等待的锁
  • 资源死锁:多个线程在相同的资源上发生等待

由于调用顺序而产生的死锁

public class Test {
    Object leftLock = new Object();
    Object rightLock = new Object();
    public static void main(String[] args) {
        final Test test = new Test();
        Thread a = new Thread(new Runnable() {
            @Override            public void run() {
               int i=0;
                while (i<10)
                {
                    test.leftRight();
                    i++;
                }
            }
        },"aThread");
        Thread b = new Thread(new Runnable() {
            @Override            public void run() {
                int i=0;
                while (i<10)
                {
                    test.rightleft();
                    i++;
                }
            }
        },"bThread");
        a.start();
        b.start();
    }

    public void leftRight(){
        synchronized (leftLock){
            System.out.println(Thread.currentThread().getName()+":leftRight:get left");
            synchronized (rightLock){
                System.out.println(Thread.currentThread().getName()+":leftRight:get right");
            }
        }
    }

    public void  rightleft(){
        synchronized (rightLock){
            System.out.println(Thread.currentThread().getName()+":rightleft: get right");
            synchronized (leftLock){
                System.out.println(Thread.currentThread().getName()+":rightleft: get left");
            }
        }
    }

}
复制代码

运行后输出如下

aThread:leftRight:get left
bThread:rightleft: get right
复制代码

可以通过jstack发现死锁的痕迹

"bThread" prio=5 tid=0x00007fabb2001000 nid=0x5503 waiting for monitor entry [0x000000011d54b000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at main.lockTest.Test.rightleft(Test.java:52)
    - waiting to lock <0x00000007aaee5748> (a java.lang.Object)
    - locked <0x00000007aaee5758> (a java.lang.Object)
    at main.lockTest.Test$2.run(Test.java:30)
    at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
    - None

"aThread" prio=5 tid=0x00007fabb2801000 nid=0x5303 waiting for monitor entry [0x000000011d448000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at main.lockTest.Test.leftRight(Test.java:43)
    - waiting to lock <0x00000007aaee5758> (a java.lang.Object)
    - locked <0x00000007aaee5748> (a java.lang.Object)
    at main.lockTest.Test$1.run(Test.java:19)
    at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
    - None
复制代码

可以看到 bThread 持有锁 0x00000007aaee5758 ,同时等待 0x00000007aaee5748 ,然而恰好 aThread 持有锁 0x00000007aaee5748 并等待 0x00000007aaee5758 ,从而形成了死锁

线程饥饿死锁

public class ExecutorLock {
    private static ExecutorService single=Executors.newSingleThreadExecutor();
    public static class AnotherCallable implements Callable<String>{

        @Override        public String call() throws Exception {
            System.out.println("in AnotherCallable");
            return "annother success";
        }
    }


    public static class MyCallable implements Callable<String>{

        @Override        public String call() throws Exception {
            System.out.println("in MyCallable");
            Future<String> submit = single.submit(new AnotherCallable());
            return "success:"+submit.get();
        }
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable task = new MyCallable();
        Future<String> submit = single.submit(task);
        System.out.println(submit.get());
        System.out.println("over");
        single.shutdown();
    }
}
复制代码

执行的输出只有一行

in MyCallable
复制代码

通过jstack观察可以看到如下

"main" prio=5 tid=0x00007fab3f000000 nid=0x1303 waiting on condition [0x0000000107d63000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007aaeed1d8> (a java.util.concurrent.FutureTask)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:425)
    at java.util.concurrent.FutureTask.get(FutureTask.java:187)
    at main.lockTest.ExecutorLock.main(ExecutorLock.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

   Locked ownable synchronizers:
    - None
..
"pool-1-thread-1" prio=5 tid=0x00007fab3f835800 nid=0x5303 waiting on condition [0x00000001199ee000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007ab0f8698> (a java.util.concurrent.FutureTask)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:425)
    at java.util.concurrent.FutureTask.get(FutureTask.java:187)
    at main.lockTest.ExecutorLock$MyCallable.call(ExecutorLock.java:26)
    at main.lockTest.ExecutorLock$MyCallable.call(ExecutorLock.java:20)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
    - <0x00000007aaeed258> (a java.util.concurrent.ThreadPoolExecutor$Worker)
复制代码

主线程在等待一个FutureTask完成,而线程池中一个线程也在等待一个FutureTask完成。

从代码实现可以看到,主线程往线程池中扔了一个任务A,任务A又往同一个线程池中扔了一个任务B,并等待B的完成,由于线程池中只有一个线程,这将导致B会被停留在阻塞队列中,而A还得等待B的完成,这也就是互相等待导致了死锁的反生

这种由于正在执行的任务线程都在等待其它工作队列中的任务而阻塞的现象称为 线程饥饿死锁


以上所述就是小编给大家介绍的《Java中常见死锁的实例》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

世界因你不同

世界因你不同

李开复、范海涛 / 中信出版社 / 2010 / 29.8

这是李开复唯一的一本自传,字里行间,是岁月流逝中沉淀下来的宝贵的人生智慧和职场经验。捣蛋的“小皇帝”,11岁的“留学生”,奥巴马的大学同学,26岁的副教授,33岁的苹果副总裁,谷歌中国的创始人,他有着太多传奇的经历,为了他,两家最大的IT公司对簿公堂。而他的每一次人生选择,都是一次成功的自我超越。   透过这本自传,李开复真诚讲述了他鲜为人知的成长史、风雨兼程的成功史和烛照人生的心灵史,也首次全面......一起来看看 《世界因你不同》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码