您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關通俗易懂的Java死鎖代碼示例,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
演示死鎖
package com.yang.kuangTeacher; import java.util.concurrent.TimeUnit; /** * @author: fudy * @date: 2020/9/13 下午 12:21 * @Decription: 演示死鎖(內容參考B站狂神說JAVA) **/ public class DeadLock { public static void main(String[] args) { MarkUp markUp0 = new MarkUp("迪麗熱巴",0); MarkUp markUp1 = new MarkUp("楊冪",1); markUp0.start(); markUp1.start(); } } // 口紅類 class LipStick { } // 鏡子類 class Mirror { } // 化妝類 class MarkUp extends Thread { private int choice; private String userName; private static LipStick lipStick = new LipStick(); private static Mirror mirror = new Mirror(); MarkUp(String userName, int choice) { this.userName = userName; this.choice = choice; } @Override public void run() { try { markUP(); } catch (InterruptedException e) { e.printStackTrace(); } } private void markUP() throws InterruptedException { // 如果選擇0方式化妝 if (choice == 0) { // 同步代碼塊的鎖,在同步代碼塊有效 synchronized (lipStick) { System.out.println(userName + "拿到了口紅"); // 拿到口紅后再拿鏡子 TimeUnit.SECONDS.sleep(1); // 程序執行此處會停止 -----------------這里死鎖-----------------------> synchronized (mirror) { System.out.println(userName + "拿到了鏡子"); } } } // 如果選擇1方式化妝 if (choice == 1) { // 同步代碼塊的鎖,在同步代碼塊有效 synchronized (mirror) { System.out.println(userName + "拿到了鏡子"); // 拿到鏡子后再拿口紅 TimeUnit.SECONDS.sleep(1); // 程序執行此處會停止 -----------------這里死鎖-----------------------> synchronized (lipStick) { System.out.println(userName + "拿到了口紅"); } } } } }
我們剛才認為,死鎖是由于同步代碼塊沒有執行完,導致不會釋放鎖,我們分析以上兩個死鎖的原因。
假如線程1先獲得口紅鎖執行完畢,準備拿鏡子鎖時,發現鏡子對象被持有了,所以他會等待鏡子鎖被釋放。
線程2先執行獲得鏡子鎖完畢,準備拿口紅鎖時,發現口紅對象被持有了,所以他會等待口紅鎖被釋放。
如果我們不關閉程序,兩個線程會一直等待下去。我們可以理解為死鎖,無法釋放鎖。
解決死鎖
在上述例子中,我們因為想同時拿到兩個鎖去做一件事情才會導致死鎖,按照Java Effective提倡減小鎖的范圍,我們對問題進行改進。
我們可以拿到口紅鎖后執行口紅方法后釋放口紅鎖,想要鏡子鎖再同步代碼塊拿鏡子鎖即可。
package com.yang.kuangTeacher; import java.util.concurrent.TimeUnit; /** * @author: fudy * @date: 2020/9/13 下午 12:21 * @Decription: 演示死鎖(內容參考B站狂神說JAVA) **/ public class DeadLock { public static void main(String[] args) { MarkUp markUp0 = new MarkUp("迪麗熱巴",0); MarkUp markUp1 = new MarkUp("楊冪",1); markUp0.start(); markUp1.start(); } } // 口紅類 class LipStick { } // 鏡子類 class Mirror { } // 化妝類 class MarkUp extends Thread { private int choice; private String userName; private static LipStick lipStick = new LipStick(); private static Mirror mirror = new Mirror(); MarkUp(String userName, int choice) { this.userName = userName; this.choice = choice; } @Override public void run() { try { markUP(); } catch (InterruptedException e) { e.printStackTrace(); } } private void markUP() throws InterruptedException { // 如果選擇0方式化妝 if (choice == 0) { // 同步代碼塊的鎖,在同步代碼塊有效 synchronized (lipStick) { System.out.println(userName + "拿到了口紅"); TimeUnit.SECONDS.sleep(1); } // 拿到口紅后再拿鏡子 ------------------------改進--------------------------- synchronized (mirror) { System.out.println(userName + "拿到了鏡子"); } } // 如果選擇1方式化妝 if (choice == 1) { // 同步代碼塊的鎖,在同步代碼塊有效 synchronized (mirror) { System.out.println(userName + "拿到了鏡子"); TimeUnit.SECONDS.sleep(1); } // 拿到鏡子后再拿口紅 ------------------------改進--------------------------- synchronized (lipStick) { System.out.println(userName + "拿到了口紅"); } } } }
通過及時釋放鎖,也就是縮小同步代碼塊的范圍,我們使用鎖結束后及時釋放,這樣是一種解決死鎖的方式,通過這個例子我們以后編寫代碼就會警惕鎖的同步代碼的范圍。
看完上述內容,你們對通俗易懂的Java死鎖代碼示例有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。