遊戲陪玩原始碼的輪詢鎖,使用時遇到的問題與解決方案
問題演示
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class DeadLockByReentrantLock { public static void main(String[] args) { Lock lockA = new ReentrantLock(); // 建立鎖 A Lock lockB = new ReentrantLock(); // 建立鎖 B // 建立執行緒 1 Thread t1 = new Thread(new Runnable() { @Override public void run() { lockA.lock(); // 加鎖 System.out.println("執行緒 1:獲取到鎖 A!"); try { Thread.sleep(1000); System.out.println("執行緒 1:等待獲取 B..."); lockB.lock(); // 加鎖 try { System.out.println("執行緒 1:獲取到鎖 B!"); } finally { lockA.unlock(); // 釋放鎖 } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockA.unlock(); // 釋放鎖 } } }); t1.start(); // 執行執行緒 // 建立執行緒 2 Thread t2 = new Thread(new Runnable() { @Override public void run() { lockB.lock(); // 加鎖 System.out.println("執行緒 2:獲取到鎖 B!"); try { Thread.sleep(1000); System.out.println("執行緒 2:等待獲取 A..."); lockA.lock(); // 加鎖 try { System.out.println("執行緒 2:獲取到鎖 A!"); } finally { lockA.unlock(); // 釋放鎖 } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockB.unlock(); // 釋放鎖 } } }); t2.start(); // 執行執行緒 }}
簡易版輪詢鎖
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SolveDeadLockExample2 { public static void main(String[] args) { Lock lockA = new ReentrantLock(); // 建立鎖 A Lock lockB = new ReentrantLock(); // 建立鎖 B // 建立執行緒 1(使用輪詢鎖) Thread t1 = new Thread(new Runnable() { @Override public void run() { // 呼叫輪詢鎖 pollingLock(lockA, lockB); } }); t1.start(); // 執行執行緒 // 建立執行緒 2 Thread t2 = new Thread(new Runnable() { @Override public void run() { lockB.lock(); // 加鎖 System.out.println("執行緒 2:獲取到鎖 B!"); try { Thread.sleep(1000); System.out.println("執行緒 2:等待獲取 A..."); lockA.lock(); // 加鎖 try { System.out.println("執行緒 2:獲取到鎖 A!"); } finally { lockA.unlock(); // 釋放鎖 } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockB.unlock(); // 釋放鎖 } } }); t2.start(); // 執行執行緒 } /** * 輪詢鎖 */ private static void pollingLock(Lock lockA, Lock lockB) { // 輪詢鎖 while (true) { if (lockA.tryLock()) { // 嘗試獲取鎖 System.out.println("執行緒 1:獲取到鎖 A!"); try { Thread.sleep(1000); System.out.println("執行緒 1:等待獲取 B..."); if (lockB.tryLock()) { // 嘗試獲取鎖 try { System.out.println("執行緒 1:獲取到鎖 B!"); } finally { lockB.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 B."); break; } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockA.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 A."); } } // 等待一秒再繼續執行 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
問題1:死迴圈
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SolveDeadLockExample { public static void main(String[] args) { Lock lockA = new ReentrantLock(); // 建立鎖 A Lock lockB = new ReentrantLock(); // 建立鎖 B // 建立執行緒 1(使用輪詢鎖) Thread t1 = new Thread(new Runnable() { @Override public void run() { // 呼叫輪詢鎖 pollingLock(lockA, lockB); } }); t1.start(); // 執行執行緒 // 建立執行緒 2 Thread t2 = new Thread(new Runnable() { @Override public void run() { lockB.lock(); // 加鎖 System.out.println("執行緒 2:獲取到鎖 B!"); try { Thread.sleep(1000); System.out.println("執行緒 2:等待獲取 A..."); lockA.lock(); // 加鎖 try { System.out.println("執行緒 2:獲取到鎖 A!"); } finally { lockA.unlock(); // 釋放鎖 } } catch (InterruptedException e) { e.printStackTrace(); } finally { // 如果此處程式碼未執行,執行緒 2 一直未釋放鎖資源 // lockB.unlock(); } } }); t2.start(); // 執行執行緒 } /** * 輪詢鎖 */ public static void pollingLock(Lock lockA, Lock lockB) { while (true) { if (lockA.tryLock()) { // 嘗試獲取鎖 System.out.println("執行緒 1:獲取到鎖 A!"); try { Thread.sleep(1000); System.out.println("執行緒 1:等待獲取 B..."); if (lockB.tryLock()) { // 嘗試獲取鎖 try { System.out.println("執行緒 1:獲取到鎖 B!"); } finally { lockB.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 B."); break; } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockA.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 A."); } } // 等待一秒再繼續執行 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SolveDeadLockExample { public static void main(String[] args) { Lock lockA = new ReentrantLock(); // 建立鎖 A Lock lockB = new ReentrantLock(); // 建立鎖 B // 建立執行緒 1(使用輪詢鎖) Thread t1 = new Thread(new Runnable() { @Override public void run() { // 呼叫輪詢鎖 pollingLock(lockA, lockB, 3); } }); t1.start(); // 執行執行緒 // 建立執行緒 2 Thread t2 = new Thread(new Runnable() { @Override public void run() { lockB.lock(); // 加鎖 System.out.println("執行緒 2:獲取到鎖 B!"); try { Thread.sleep(1000); System.out.println("執行緒 2:等待獲取 A..."); lockA.lock(); // 加鎖 try { System.out.println("執行緒 2:獲取到鎖 A!"); } finally { lockA.unlock(); // 釋放鎖 } } catch (InterruptedException e) { e.printStackTrace(); } finally { // 執行緒 2 忘記釋放鎖資源 // lockB.unlock(); // 釋放鎖 } } }); t2.start(); // 執行執行緒 } /** * 輪詢鎖 * * maxCount:最大輪詢次數 */ public static void pollingLock(Lock lockA, Lock lockB, int maxCount) { // 輪詢次數計數器 int count = 0; while (true) { if (lockA.tryLock()) { // 嘗試獲取鎖 System.out.println("執行緒 1:獲取到鎖 A!"); try { Thread.sleep(1000); System.out.println("執行緒 1:等待獲取 B..."); if (lockB.tryLock()) { // 嘗試獲取鎖 try { System.out.println("執行緒 1:獲取到鎖 B!"); } finally { lockB.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 B."); break; } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockA.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 A."); } } // 判斷是否已經超過最大次數限制 if (count++ > maxCount) { // 終止迴圈 System.out.println("輪詢鎖獲取失敗,記錄日誌或執行其他失敗策略"); return; } // 等待一秒再繼續嘗試獲取鎖 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
問題2:執行緒餓死
// 等待 1s 再嘗試獲取(輪詢)鎖try { Thread.sleep(1000);} catch (InterruptedException e) { e.printStackTrace();}
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SolveDeadLockExample { public static void main(String[] args) { Lock lockA = new ReentrantLock(); // 建立鎖 A Lock lockB = new ReentrantLock(); // 建立鎖 B // 建立執行緒 1(使用輪詢鎖) Thread t1 = new Thread(new Runnable() { @Override public void run() { // 呼叫輪詢鎖 pollingLock(lockA, lockB, 3); } }); t1.start(); // 執行執行緒 // 建立執行緒 2 Thread t2 = new Thread(new Runnable() { @Override public void run() { while (true) { lockB.lock(); // 加鎖 System.out.println("執行緒 2:獲取到鎖 B!"); try { System.out.println("執行緒 2:等待獲取 A..."); lockA.lock(); // 加鎖 try { System.out.println("執行緒 2:獲取到鎖 A!"); } finally { lockA.unlock(); // 釋放鎖 } } finally { lockB.unlock(); // 釋放鎖 } // 等待一秒之後繼續執行 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t2.start(); // 執行執行緒 } /** * 輪詢鎖 */ public static void pollingLock(Lock lockA, Lock lockB, int maxCount) { // 迴圈次數計數器 int count = 0; while (true) { if (lockA.tryLock()) { // 嘗試獲取鎖 System.out.println("執行緒 1:獲取到鎖 A!"); try { Thread.sleep(100); // 等待 0.1s(獲取鎖需要的時間) System.out.println("執行緒 1:等待獲取 B..."); if (lockB.tryLock()) { // 嘗試獲取鎖 try { System.out.println("執行緒 1:獲取到鎖 B!"); } finally { lockB.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 B."); break; } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockA.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 A."); } } // 判斷是否已經超過最大次數限制 if (count++ > maxCount) { // 終止迴圈 System.out.println("輪詢鎖獲取失敗,記錄日誌或執行其他失敗策略"); return; } // 等待一秒再繼續嘗試獲取鎖 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
import java.util.Random;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class SolveDeadLockExample { private static Random rdm = new Random(); public static void main(String[] args) { Lock lockA = new ReentrantLock(); // 建立鎖 A Lock lockB = new ReentrantLock(); // 建立鎖 B // 建立執行緒 1(使用輪詢鎖) Thread t1 = new Thread(new Runnable() { @Override public void run() { // 呼叫輪詢鎖 pollingLock(lockA, lockB, 3); } }); t1.start(); // 執行執行緒 // 建立執行緒 2 Thread t2 = new Thread(new Runnable() { @Override public void run() { while (true) { lockB.lock(); // 加鎖 System.out.println("執行緒 2:獲取到鎖 B!"); try { System.out.println("執行緒 2:等待獲取 A..."); lockA.lock(); // 加鎖 try { System.out.println("執行緒 2:獲取到鎖 A!"); } finally { lockA.unlock(); // 釋放鎖 } } finally { lockB.unlock(); // 釋放鎖 } // 等待一秒之後繼續執行 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t2.start(); // 執行執行緒 } /** * 輪詢鎖 */ public static void pollingLock(Lock lockA, Lock lockB, int maxCount) { // 迴圈次數計數器 int count = 0; while (true) { if (lockA.tryLock()) { // 嘗試獲取鎖 System.out.println("執行緒 1:獲取到鎖 A!"); try { Thread.sleep(100); // 等待 0.1s(獲取鎖需要的時間) System.out.println("執行緒 1:等待獲取 B..."); if (lockB.tryLock()) { // 嘗試獲取鎖 try { System.out.println("執行緒 1:獲取到鎖 B!"); } finally { lockB.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 B."); break; } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockA.unlock(); // 釋放鎖 System.out.println("執行緒 1:釋放鎖 A."); } } // 判斷是否已經超過最大次數限制 if (count++ > maxCount) { // 終止迴圈 System.out.println("輪詢鎖獲取失敗,記錄日誌或執行其他失敗策略"); return; } // 等待一定時間(固定時間 + 隨機時間)之後再繼續嘗試獲取鎖 try { Thread.sleep(300 + rdm.nextInt(8) * 100); // 固定時間 + 隨機時間 } catch (InterruptedException e) { e.printStackTrace(); } } }}
總結
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2846015/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 玩Deno遇到問題的解決方案
- 如何用分散式鎖解決陪玩平臺原始碼中的併發問題?分散式原始碼
- Spring Boot + Redis 解決陪玩平臺原始碼重複提交問題Spring BootRedis原始碼
- 如何利用限流解決遊戲陪玩app開發中的重複提交問題?遊戲APP
- 使用EasyX製作遊戲需要讀寫檔案時遇到編碼問題的解決方法遊戲
- 陪玩原始碼,與時間、日期相關的程式碼分析原始碼
- 資料安全,是陪玩遊戲系統時刻關注的問題遊戲
- 使用nodeAPI時遇到非同步問題的解決方法API非同步
- 遊戲陪玩平臺原始碼,日期格式化的程式碼分析遊戲原始碼
- 帶你瞭解遊戲陪玩系統原始碼前端常用的儲存方式遊戲原始碼前端
- 原始碼安裝apache(附遇到的問題及解決)原始碼Apache
- 遊戲陪玩app原始碼開發,常用的倒數計時功能如何實現?遊戲APP原始碼
- 陪玩平臺原始碼中的CDN服務不可用時的解決辦法原始碼
- 遊戲陪玩app原始碼的可靠訊息最終一致性方案的實現遊戲APP原始碼
- Netty中使用MessagePack時的TCP粘包問題與解決方案NettyTCP
- 遊戲陪玩APP遊戲APP
- 遊戲陪玩app原始碼開發,啟動速度優化與監控遊戲APP原始碼優化
- 用conda安裝庫時遇到環境查詢失敗問題解決方案
- Java 8 的日期與時間問題解決方案Java
- 遊戲陪玩app開發,前端實現一個輪詢需要如何做?遊戲APP前端
- 遊戲陪玩原始碼的登入方式,簡訊驗證碼登入的實現遊戲原始碼
- 在遊戲陪玩原始碼開發中,兩種清空陣列的方式遊戲原始碼陣列
- 遊戲陪玩原始碼前端開發,不容忽視的五個要點遊戲原始碼前端
- 遊戲陪玩原始碼前端圖片載入優化的各種技巧遊戲原始碼前端優化
- 遊戲陪玩原始碼的移動端適配,應該如何實現?遊戲原始碼
- Composer 使用過程中遇到的問題和解決方案
- 遇到問題的解決方法
- Lumen 中使用 jwt 時多 guard 的問題解決方案JWT
- 用 Go + Redis 實現陪玩平臺原始碼中的分散式鎖GoRedis原始碼分散式
- 要想實現遊戲陪玩app原始碼的效能測試與調優,應該怎麼做?遊戲APP原始碼
- 如何實現遊戲陪玩系統原始碼前端效能監控?遊戲原始碼前端
- 遇到的編碼問題、時區問題整理
- 遊戲陪玩原始碼前端效能優化,開發階段可採取的措施遊戲原始碼前端優化
- 遊戲陪玩平臺原始碼開發,依賴收集和觸發的實現遊戲原始碼
- 遊戲陪玩系統原始碼中不同排序演算法的實現方式遊戲原始碼排序演算法
- 什麼是遊戲陪玩app原始碼開發的過度設計,如何避免?遊戲APP原始碼
- 遊戲陪玩,仍在途中遊戲
- 來玩遊戲嗎?能線上陪玩的那種。遊戲