Java中的鎖是什么?


在並發編程中,經常會遇到多個線程訪問同一個共享變量,當同時對共享變量進行讀寫操作時,就會產生數據不一致的情況。


為了解決這個問題

  • JDK 1.5 之前,使用 synchronized 關鍵字,拿到 Java 對象的鎖,保護鎖定的代碼塊。JVM 保證同一時刻只有一個線程可以拿到這個 Java 對象的鎖,執行對應的代碼塊。
  • JDK 1.5 開始,引入了並發工具包 java.util.concurrent.locks.Lock,讓鎖的功能更加豐富。

 

常見的鎖

  • synchronized 關鍵字鎖定代碼庫
  • 可重入鎖 java.util.concurrent.lock.ReentrantLock
  • 可重復讀寫鎖 java.util.concurrent.lock.ReentrantReadWriteLock

 

Java 中不同維度的鎖分類

可重入鎖

  • 指在同一個線程在外層方法獲取鎖的時候,進入內層方法會自動獲取鎖。JDK 中基本都是可重入鎖,避免死鎖的發生。上面提到的常見的鎖都是可重入鎖。

 

公平鎖 / 非公平鎖

  • 公平鎖,指多個線程按照申請鎖的順序來獲取鎖。如 java.util.concurrent.lock.ReentrantLock.FairSync
  • 非公平鎖,指多個線程獲取鎖的順序並不是按照申請鎖的順序,有可能后申請的線程先獲得鎖。如 synchronized、java.util.concurrent.lock.ReentrantLock.NonfairSync

        
獨享鎖 / 共享鎖

  • 獨享鎖,指鎖一次只能被一個線程所持有。synchronized、java.util.concurrent.locks.ReentrantLock 都是獨享鎖
  • 共享鎖,指鎖可被多個線程所持有。ReadWriteLock 返回的 ReadLock 就是共享鎖

          
悲觀鎖 / 樂觀鎖

  • 悲觀鎖,一律會對代碼塊進行加鎖,如 synchronized、java.util.concurrent.locks.ReentrantLock
  • 樂觀鎖,默認不會進行並發修改,通常采用 CAS 算法不斷嘗試更新
  • 悲觀鎖適合寫操作較多的場景,樂觀鎖適合讀操作較多的場景

        
粗粒度鎖 / 細粒度鎖

  • 粗粒度鎖,就是把執行的代碼塊都鎖定
  • 細粒度鎖,就是鎖住盡可能小的代碼塊,java.util.concurrent.ConcurrentHashMap 中的分段鎖就是一種細粒度鎖
  • 粗粒度鎖和細粒度鎖是相對的,沒有什么標准

        
偏向鎖 / 輕量級鎖 / 重量級鎖

  • JDK 1.5 之后新增鎖的升級機制,提升性能。
  • 通過 synchronized 加鎖后,一段同步代碼一直被同一個線程所訪問,那么該線程獲取的就是偏向鎖
  • 偏向鎖被一個其他線程訪問時,Java 對象的偏向鎖就會升級為輕量級鎖
  • 再有其他線程會以自旋的形式嘗試獲取鎖,不會阻塞,自旋一定次數仍然未獲取到鎖,就會膨脹為重量級鎖        

        
自旋鎖

  • 自旋鎖是指嘗試獲取鎖的線程不會立即阻塞,而是采用循環的方式去嘗試獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環占有、浪費 CPU 資源


 


 

所有資源資源匯總於公眾號



 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM