Java 中的鎖

今天是九一八事變爆發 88 週年,國恥日。java


每當我看到祖國的航空航天、互聯網、5G 這些科技方面趕超美國的新聞時,我心裏都異常激動,從 "東亞病夫" 到吾輩自強,靠得是無數中華兒女的實幹。算法


銘記歷史...編程





工做再忙,仍是但願堅持把編程知識分享下去,繼續 Java 併發編程。併發


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


爲了解決這個問題ide

  • JDK 1.5 以前,使用 synchronized 關鍵字,拿到 Java 對象的鎖,保護鎖定的代碼塊。JVM 保證同一時刻只有一個線程能夠拿到這個 Java 對象的鎖,執行對應的代碼塊。工具

  • JDK 1.5 開始,引入了併發工具包 java.util.concurrent.locks.Lock,讓鎖的功能更加豐富。性能

 

常見的鎖

  • synchronized 關鍵字鎖定代碼庫spa

  • 可重入鎖 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 資源

相關文章
相關標籤/搜索