Lock鎖子類瞭解一下

前言

回顧前面:微信

只有光頭才能變強!多線程

上一篇已經將Lock鎖的基礎AQS簡單地過了一遍了,所以本篇主要是講解Lock鎖主要的兩個子類:框架

  • ReentrantLock
  • ReentrantReadWriteLock

那麼接下來咱們就開始吧~post

1、ReentrantLock鎖

首先咱們來看看ReentrantLock鎖的頂部註釋,來看看他的相關特性唄:學習

 

 

來總結一下要點吧:ui

  • 比synchronized更有伸縮性(靈活)
  • 支持公平鎖(是相對公平的)
  • 使用時最標準用法是在try以前調用lock方法,在finally代碼塊釋放鎖
class X {
    private final ReentrantLock lock = new ReentrantLock();
    // ...

    public void m() { 
        lock.lock();  // block until condition holds
        try {
            // ... method body
        } finally {
            lock.unlock()
        }
    }
}

1.1內部類

首先咱們能夠看到有三個內部類:spa

 

 

這些內部類都是AQS的子類,這就印證了咱們以前所說的:AQS是ReentrantLock的基礎,AQS是構建鎖、同步器的框架線程

  • 能夠很清晰的看到,咱們的ReentrantLock鎖是支持公平鎖和非公平鎖的~

 

 

1.2構造方法

 

 

1.3非公平lock方法

嘗試獲取鎖,獲取失敗的話就調用AQS的acquire(1)方法3d

 

 

acquire(1)方法咱們在AQS時簡單看過,其中tryAcquire()是子類來實現的code

 

 

咱們去看看tryAcquire()

 

 

1.4公平lock方法

公平的lock方法其實就多了一個狀態條件

 

 

這個方法主要是判斷當前線程是否位於CLH同步隊列中的第一個。若是是則返回flase,不然返回true

 

 

1.5unlock方法

 

 

unlock方法也是在AQS中定義的:

 

 

去看看tryRelease(arg)是怎麼實現的:

 

 

2、ReentrantReadWriteLock

咱們知道synchronized內置鎖和ReentrantLock都是互斥鎖(一次只能有一個線程進入到臨界區(被鎖定的區域))

而ReentrantReadWriteLock是一個讀寫鎖

  • 取數據的時候,能夠多個線程同時進入到到臨界區(被鎖定的區域)
  • 數據的時候,不管是讀線程仍是寫線程都是互斥

通常來講:咱們大多數都是讀取數據得多,修改數據得少。因此這個讀寫鎖在這種場景下就頗有用了!

讀寫鎖有一個接口ReadWriteLock,定義的方法就兩個:

 

 

咱們仍是來看看頂部註釋說得啥吧:

 

 

其實大概也是說明了:在讀的時候能夠共享,在寫的時候是互斥的

接下來咱們仍是來看看對應的實現類吧:

 

 

按照慣例也簡單看看它的頂部註釋:

 

 

因而咱們能夠總結出讀寫鎖的一些要點了:

  • 讀鎖不支持條件對象,寫鎖支持條件對象
  • 讀鎖不能升級爲寫鎖,寫鎖能夠降級爲讀鎖
  • 讀寫鎖也有公平和非公平模式
  • 讀鎖支持多個讀線程進入臨界區,寫鎖是互斥的

2.1ReentrantReadWriteLock內部類

ReentrantReadWriteLock比ReentrantLock鎖多了兩個內部類(都是Lock實現)來維護讀鎖和寫鎖,可是主體仍是使用Syn

  • WriteLock
  • ReadLock

 

 

2.2讀鎖和寫鎖的狀態表示

在ReentrantLock鎖上使用的是state來表示同步狀態(也能夠表示重入的次數),而在ReentrantReadWriteLock是這樣表明讀寫狀態的:

 

 

2.3寫鎖的獲取

主要仍是調用syn的acquire(1)

 

 

進去看看實現:

 

 

2.4讀鎖獲取

寫鎖的獲取調用的是acquireShared(int arg)方法:

 

 

內部調用的是:doAcquireShared(arg);方法(實現也是在Syn的),咱們來看看:

 

 

3、最後

這裏就簡單總結一下本文的內容吧:

  • AQS是ReentrantReadWriteLock和ReentrantLock的基礎,由於默認的實現都是在內部類Syn中,而Syn是繼承AQS的~
  • ReentrantReadWriteLock和ReentrantLock都支持公平和非公平模式,公平模式下會去看FIFO隊列線程是不是在隊頭,而非公平模式下是沒有的
  • ReentrantReadWriteLock是一個讀寫鎖,若是讀的線程比寫的線程要多不少的話,那能夠考慮使用它。它使用state的變量高16位是讀鎖,低16位是寫鎖
  • 寫鎖能夠降級爲讀鎖,讀鎖不能升級爲寫鎖
  • 寫鎖是互斥的,讀鎖是共享的

總的來講看多線程源碼難度係數仍是好高啊,我目前的水平只能過一過了....

多線程後面還有挺多高深的知識點:Future、同步容器啊、阻塞隊列、各類原子類啊等等等,這裏我打算就先放一放了,目前的水平有限啊~~~~~

後面可能會有一篇線程池的博文,敬請期待咯~

有興趣的同窗可繼續往下面的參考資料下學習~~~

參考資料:

若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:Java3y。爲了你們方便,剛新建了一下qq羣:742919422,你們也能夠去交流交流。謝謝支持了!但願能多介紹給其餘有須要的朋友

文章的目錄導航

相關文章
相關標籤/搜索