java執行緒死鎖例項
阿新 • • 發佈:2019-01-10
死鎖發生的四個必要條件:
1、互斥使用,即當資源被一個執行緒使用(佔有)時,別的執行緒不能使用
2、不可搶佔,資源請求者不能強制從資源佔有者手中奪取資源,資源只能由資源佔有者主動釋放。
3、請求和保持,即當資源請求者在請求其他的資源的同時保持對原有資源的佔有。
4、迴圈等待,即存在一個等待佇列:P1佔有P2的資源,P2佔有P3的資源,P3佔有P1的資源。這樣就形成了一個等待環路。
上面四個條件同時成立時就會產生死鎖,如果消除任何一個條件就可以消除死鎖。
下面是一個死鎖發生的例項:
上面的例項在執行時會發生死鎖,也就是兩個執行緒分別等待另一個執行緒釋放資源,但另一個執行緒被synchronized關鍵字修飾,不能直接釋放資源,所以造成的結果就是相互等待,程式直接掛掉了。package com.cy.test; public class Sisuo { public static Object object1; public static Object object2; public static class MyRunnable implements Runnable { int flag; public MyRunnable(int flag) { this.flag = flag; } @Override public void run() { if (flag == 1) { synchronized (object1) { for(int i=0;i<10000;i++);//擴大死鎖發生機率 //或者Thread.sleep(50); synchronized (object2) { System.out.println("1"); } } } else if (flag == 2) { synchronized (object2) { for(int i=0;i<10000;i++); //或者Thread.sleep(50); synchronized (object1) { System.out.println("2"); } } } } } public static void main(String[] args) { object1 = new Object(); object2 = new Object(); new Thread(new MyRunnable(1)).start(); new Thread(new MyRunnable(2)).start(); } }
下面主要分析一下發生死鎖的原因:
從上面的程式來看,改程式主要使用了兩把鎖,分別是執行緒1對資源object1佔有資源的同時又對object2申請資源,並想佔有,同時執行緒2對資源object2佔有資源的同時又對object1申請資源,如果我們刪除兩個鎖之間的迴圈語句,最後得到的結果可能是能正常執行的,那麼為什麼這種情況沒有死鎖呢,其實是因為cpu的執行速度非常快,此時執行緒1佔有了資源object1,並很快又佔據資源object2,此時執行緒2想要申請object2的時候,資源已經被執行緒1佔有,所以此時等待執行緒1執行完畢,最後輸出的結果就會是12或者21,但是如果在兩個鎖之間加了運算稍微大的運算,那麼最後的結果就是執行緒1已經佔據資源object1,執行緒2已經佔據資源object2,此時執行緒1申請資源object2時,已經被執行緒2佔有,而此時執行緒2申請資源object1時又被執行緒1佔有,此時兩者都不能釋放各自佔有的資源,因為用synchronized關鍵字所修飾,所以最後的結果就會是相互等待而系統直接掛掉