<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### 獨享鎖vs共享鎖 * 獨享鎖也叫排他鎖,是指該鎖一次只能被一個線程所持有。如果線程T對數據A加上排它鎖后,則其他線程不能再對A加任何類型的鎖。獲得排它鎖的線程即能讀數據又能修改數據。JDK中的synchronized和JUC中Lock的實現類就是互斥鎖。 * 共享鎖是指該鎖可被多個線程所持有。如果線程T對數據A加上共享鎖后,則其他線程只能對A再加共享鎖,不能加排它鎖。獲得共享鎖的線程只能讀數據,不能修改數據 獨享鎖與共享鎖也是通過AQS來實現的,通過實現不同的方法,來實現獨享或者共享。 下圖為ReentrantReadWriteLock的部分源碼: ![](https://img.kancloud.cn/06/1b/061b74937214dd0a231c5c705376cd52_1080x628.png) 我們看到ReentrantReadWriteLock有兩把鎖:ReadLock和WriteLock,由詞知意,一個讀鎖一個寫鎖,合稱“讀寫鎖”。再進一步觀察可以發現ReadLock和WriteLock是靠內部類Sync實現的鎖。Sync是AQS的一個子類,這種結構在CountDownLatch、ReentrantLock、Semaphore里面也都存在。 在ReentrantReadWriteLock里面,讀鎖和寫鎖的鎖主體都是Sync,但讀鎖和寫鎖的加鎖方式不一樣。讀鎖是共享鎖,寫鎖是獨享鎖。讀鎖的共享鎖可保證并發讀非常高效,而讀寫、寫讀、寫寫的過程互斥,因為讀鎖和寫鎖是分離的。所以ReentrantReadWriteLock的并發性相比一般的互斥鎖有了很大提升。 那讀鎖和寫鎖的具體加鎖方式有什么區別呢?在了解源碼之前我們需要回顧一下其他知識 在最開始提及AQS的時候我們也提到了state字段(int類型,32位),該字段用來描述有多少線程獲持有鎖。 在獨享鎖中這個值通常是0或者1(如果是重入鎖的話state值就是重入的次數),在共享鎖中state就是持有鎖的數量。但是在ReentrantReadWriteLock中有讀、寫兩把鎖,所以需要在一個整型變量state上分別描述讀鎖和寫鎖的數量(或者也可以叫狀態)。于是將state變量“按位切割”切分成了兩個部分,高16位表示讀鎖狀態(讀鎖個數),低16位表示寫鎖狀態(寫鎖個數)。如下圖所示: ![](https://img.kancloud.cn/44/9a/449a25cbe08b8b74cb5d8423821953aa_1080x112.png) 了解了概念之后我們再來看代碼,先看寫鎖的加鎖源碼: ![](https://img.kancloud.cn/4e/ea/4eea95651355cca694bcb53c57fbe47e_1080x536.png) * 這段代碼首先取到當前鎖的個數c,然后再通過c來獲取寫鎖的個數w。因為寫鎖是低16位,所以取低16位的最大值與當前的c做與運算(?int w = exclusiveCount(c);?),高16位和0與運算后是0,剩下的就是低位運算的值,同時也是持有寫鎖的線程數目。 * 在取到寫鎖線程的數目后,首先判斷是否已經有線程持有了鎖。如果已經有線程持有了鎖(c!=0),則查看當前寫鎖線程的數目,如果寫線程數為0(即此時存在讀鎖)或者持有鎖的線程不是當前線程就返回失敗(涉及到公平鎖和非公平鎖的實現) * 如果寫入鎖的數量大于最大數(65535,2的16次方-1)就拋出一個Error * 如果當且寫線程數為0(那么讀線程也應該為0,因為上面已經處理c!=0的情況),并且當前線程需要阻塞那么就返回失敗;如果通過CAS增加寫線程數失敗也返回失敗 * 如果c=0,w=0或者c>0,w>0(重入),則設置當前線程或鎖的擁有者,返回成功 tryAcquire()除了重入條件(當前線程為獲取了寫鎖的線程)之外,增加了一個讀鎖是否存在的判斷。如果存在讀鎖,則寫鎖不能被獲取,原因在于:必須確保寫鎖的操作對讀鎖可見,如果允許讀鎖在已被獲取的情況下對寫鎖的獲取,那么正在運行的其他讀線程就無法感知到當前寫線程的操作。 因此,只有等待其他讀線程都釋放了讀鎖,寫鎖才能被當前線程獲取,而寫鎖一旦被獲取,則其他讀寫線程的后續訪問均被阻塞。寫鎖的釋放與ReentrantLock的釋放過程基本類似,每次釋放均減少寫狀態,當寫狀態為0時表示寫鎖已被釋放,然后等待的讀寫線程才能夠繼續訪問讀寫鎖,同時前次寫線程的修改對后續的讀寫線程可見。 接著是讀鎖的代碼: ![](https://img.kancloud.cn/5b/b1/5bb1767eca6d3183cacb850392b41e7c_1080x594.png) 可以看到在tryAcquireShared(int unused)方法中,如果其他線程已經獲取了寫鎖,則當前線程獲取讀鎖失敗,進入等待狀態。如果當前線程獲取了寫鎖或者寫鎖未被獲取,則當前線程(線程安全,依靠CAS保證)增加讀狀態,成功獲取讀鎖。讀鎖的每次釋放(線程安全的,可能有多個讀線程同時釋放讀鎖)均減少讀狀態,減少的值是“1<<16”。所以讀寫鎖才能實現讀讀的過程共享,而讀寫、寫讀、寫寫的過程互斥。 此時,我們再回頭看一下互斥鎖ReentrantLock中公平鎖和非公平鎖的加鎖源碼: ![](https://img.kancloud.cn/9d/a1/9da1fae153a3d87d6c420f5fda19fc07_1080x543.png) 我們發現在ReentrantLock雖然有公平鎖和非公平鎖兩種,但是它們添加的都是獨享鎖。根據源碼所示,當某一個線程調用lock方法獲取鎖時,如果同步資源沒有被其他線程鎖住,那么當前線程在使用CAS更新state成功后就會成功搶占該資源。而如果公共資源被占用且不是被當前線程占用,那么就會加鎖失敗。所以可以確定ReentrantLock無論讀操作還是寫操作,添加的鎖都是都是獨享鎖
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看