Java中常见死锁与活锁的实例

发布时间:2019-11-17 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Java中常见死锁与活锁的实例脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
  • 顺序死锁:过度加锁,导致由于执行顺序的原因,互相持有对方正在等待的锁
  • 死锁:多个线程在相同的资源上发生等待

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

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

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

活锁

并未产生线程阻塞,但是由于某种问题的存在,导致无法继续执行的情况。

  1. 消息重试。当某个消息处理失败的时候,一直重试,但重试由于某种原因,比如消息格式不对,导致解析失败,而它又被重试

    这种时候一般是将不可修复的错误不要重试,或者是重试次数限定
  2. 相互协作的线程彼此响应从而修改自己状态,导致无法执行下去。比如两个很有礼貌的人在同一条路上相遇,彼此给对方让路,但是又在同一条路上遇到了。互相之间反复的避让下去

    这种时候可以选择一个随机退让,使得具备一定的随机性

脚本宝典总结

以上是脚本宝典为你收集整理的Java中常见死锁与活锁的实例全部内容,希望文章能够帮你解决Java中常见死锁与活锁的实例所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。