摘要:比如兩個(gè)很有禮貌的人在同一條路上相遇,彼此給對(duì)方讓路,但是又在同一條路上遇到了。互相之間反復(fù)的避讓下去這種時(shí)候可以選擇一個(gè)隨機(jī)退讓,使得具備一定的隨機(jī)性
順序死鎖:過度加鎖,導(dǎo)致由于執(zhí)行順序的原因,互相持有對(duì)方正在等待的鎖
資源死鎖:多個(gè)線程在相同的資源上發(fā)生等待
由于調(diào)用順序而產(chǎn)生的死鎖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"); } } } }
運(yùn)行后輸出如下
aThread:leftRight:get left bThread:rightleft: get right
可以通過jstack發(fā)現(xiàn)死鎖的痕跡
"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,同時(shí)等待0x00000007aaee5748,然而恰好aThread持有鎖0x00000007aaee5748并等待0x00000007aaee5758,從而形成了死鎖
線程饑餓死鎖public class ExecutorLock { private static ExecutorService single=Executors.newSingleThreadExecutor(); public static class AnotherCallable implements Callable{ @Override public String call() throws Exception { System.out.println("in AnotherCallable"); return "annother success"; } } public static class MyCallable implements Callable { @Override public String call() throws Exception { System.out.println("in MyCallable"); Future submit = single.submit(new AnotherCallable()); return "success:"+submit.get(); } } public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable task = new MyCallable(); Future submit = single.submit(task); System.out.println(submit.get()); System.out.println("over"); single.shutdown(); } }
執(zhí)行的輸出只有一行
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)
主線程在等待一個(gè)FutureTask完成,而線程池中一個(gè)線程也在等待一個(gè)FutureTask完成。
從代碼實(shí)現(xiàn)可以看到,主線程往線程池中扔了一個(gè)任務(wù)A,任務(wù)A又往同一個(gè)線程池中扔了一個(gè)任務(wù)B,并等待B的完成,由于線程池中只有一個(gè)線程,這將導(dǎo)致B會(huì)被停留在阻塞隊(duì)列中,而A還得等待B的完成,這也就是互相等待導(dǎo)致了死鎖的反生
這種由于正在執(zhí)行的任務(wù)線程都在等待其它工作隊(duì)列中的任務(wù)而阻塞的現(xiàn)象稱為 線程饑餓死鎖活鎖
并未產(chǎn)生線程阻塞,但是由于某種問題的存在,導(dǎo)致無法繼續(xù)執(zhí)行的情況。
消息重試。當(dāng)某個(gè)消息處理失敗的時(shí)候,一直重試,但重試由于某種原因,比如消息格式不對(duì),導(dǎo)致解析失敗,而它又被重試
這種時(shí)候一般是將不可修復(fù)的錯(cuò)誤不要重試,或者是重試次數(shù)限定
相互協(xié)作的線程彼此響應(yīng)從而修改自己狀態(tài),導(dǎo)致無法執(zhí)行下去。比如兩個(gè)很有禮貌的人在同一條路上相遇,彼此給對(duì)方讓路,但是又在同一條路上遇到了。互相之間反復(fù)的避讓下去
這種時(shí)候可以選擇一個(gè)隨機(jī)退讓,使得具備一定的隨機(jī)性
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/72390.html
摘要:產(chǎn)生死鎖的必要條件互斥條件所謂互斥就是進(jìn)程在某一時(shí)間內(nèi)獨(dú)占資源。活鎖和死鎖的區(qū)別在于,處于活鎖的實(shí)體是在不斷的改變狀態(tài),所謂的活,而處于死鎖的實(shí)體表現(xiàn)為等待活鎖有可能自行解開,死鎖則不能。 死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程(或線程)在執(zhí)行過程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。 產(chǎn)生死鎖的必要條件: 互斥條件:所謂互斥就是進(jìn)程在某一時(shí)間內(nèi)獨(dú)占資...
摘要:線程安全的概念什么時(shí)候線程不安全怎樣做到線程安全怎么擴(kuò)展線程安全的類對(duì)線程安全的支持對(duì)線程安全支持有哪些中的線程池的使用與中線程池的生命周期與線程中斷中的鎖中常見死鎖與活鎖的實(shí)例線程同步機(jī)制顯示鎖使用與原理原理剖析原理中的與原理偏向鎖狀態(tài) showImg(https://segmentfault.com/img/bVblUE9?w=1354&h=1660); 線程安全的概念 showI...
摘要:對(duì)象改變條件對(duì)象當(dāng)前線程要等待線程終止之后才能從返回。如果線程在上的操作中被中斷,通道會(huì)被關(guān)閉,線程的中斷狀態(tài)會(huì)被設(shè)置,并得到一個(gè)。清除線程的中斷狀態(tài)。非公平性鎖雖然可能造成饑餓,但極少的線程切換,保證其更大的吞吐量。 聲明:Java并發(fā)的內(nèi)容是自己閱讀《Java并發(fā)編程實(shí)戰(zhàn)》和《Java并發(fā)編程的藝術(shù)》整理來的。 showImg(https://segmentfault.com/im...
摘要:異步非阻塞方式,任務(wù)的完成的通知由其他線程發(fā)出。并發(fā)并行死鎖饑餓活鎖死鎖線程持有,線程持有。如等,在多線程情況下,該操作不是原子級(jí)別的而是原子的,所以一般用于狀態(tài)標(biāo)記。 同步/異步、阻塞/非阻塞 同步/異步是 API 被調(diào)用者的通知方式。阻塞/非阻塞則是 API 調(diào)用者的等待方式(線程掛機(jī)/不掛起)。 同步非阻塞 Future方式,任務(wù)的完成要主線程自己判斷。如NIO,后臺(tái)有多個(gè)任務(wù)在...
摘要:并發(fā)模塊本身有兩種不同的類型進(jìn)程和線程,兩個(gè)基本的執(zhí)行單元。調(diào)用以啟動(dòng)新線程。在大多數(shù)系統(tǒng)中,時(shí)間片發(fā)生不可預(yù)知的和非確定性的,這意味著線程可能隨時(shí)暫停或恢復(fù)。 大綱 什么是并發(fā)編程?進(jìn)程,線程和時(shí)間片交織和競(jìng)爭(zhēng)條件線程安全 策略1:監(jiān)禁 策略2:不可變性 策略3:使用線程安全數(shù)據(jù)類型 策略4:鎖定和同步 如何做安全論證總結(jié) 什么是并發(fā)編程? 并發(fā)并發(fā)性:多個(gè)計(jì)算同時(shí)發(fā)生。 在現(xiàn)代...
閱讀 2263·2021-09-28 09:36
閱讀 1996·2021-09-22 15:14
閱讀 3623·2019-08-30 12:47
閱讀 3034·2019-08-30 12:44
閱讀 1226·2019-08-29 17:06
閱讀 536·2019-08-29 14:12
閱讀 973·2019-08-29 14:01
閱讀 2581·2019-08-29 12:17