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中常见死锁的实例》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

软件测试经验与教训

软件测试经验与教训

Cem Kaner、James Bach、Bret Pettichord / 机械工业出版社 / 2004-1 / 35.00

本书汇总了293条来自软件测试界顶尖专家的经验与建议,阐述了如何做好测试工作、如何管理测试,以及如何澄清有关软件测试的常见误解,读者可直接将这些建议用于自己的测试项目工作中。这些经验中的每一条都是与软件测试有关的一个观点,观点后面是针对运用该测试经验的方法、时机和原因的解释或例子。 本书还提供了有关如何将本书提供的经验有选择性地运用到读者实际项目环境中的建议,在所有关键问题上所积累的经验,以......一起来看看 《软件测试经验与教训》 这本书的介绍吧!

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

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具