Java中的鎖機制分為悲觀鎖和樂觀鎖。這兩種鎖機制在實現上有較大的區別,下面我們來進行介紹。
1.悲觀鎖
悲觀鎖假定自己在使用共享資源時會發生沖突,所以在訪問前先要獲取鎖,以確保自己獨占資源。如果沒有獲取到鎖,就會進入等待狀態。
synchronized(obj) { //臨界區 ... }
悲觀鎖使用synchronized關鍵字實現,具有以下特點:
- 效率較低,因為等待獲取鎖的線程會進入阻塞狀態,而且只能有一個線程訪問共享資源。
- 簡單易用,在多線程編程中使用較為常見。
2.樂觀鎖
樂觀鎖則不會認為自己在使用共享資源時會有沖突,所以對共享資源的訪問沒有加鎖。但是在寫回共享資源時,需要先檢查是否被其它線程修改,如果沒有被修改則寫回,否則重新讀取數據進行重試。
int version = 1; while(true) { try { //讀取數據 ... //修改數據 ... //嘗試寫回數據 if(version == oldVersion) { //寫回成功 break; } } catch(OptimisticLockException e) { //重試 version = oldVersion; } }
樂觀鎖的實現方式有CAS算法、版本號等,具有以下特點:
- 效率較高,因為沒有加鎖,可以有多個線程同時訪問共享資源。
- 實現比較復雜,會增加代碼的復雜度。
總結
在多線程編程中,悲觀鎖和樂觀鎖都有自己的應用場景,需要根據具體情況進行選擇。悲觀鎖適用于對數據修改操作比較頻繁的場景,樂觀鎖適用于對數據讀取操作比較頻繁的場景。