<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          了解可重入鎖和不可重入鎖的區(qū)別及原理嗎

          共 5532字,需瀏覽 12分鐘

           ·

          2021-07-03 14:37

          首先我們這里提到的鎖,是把所需要的代碼塊,資源,或數(shù)據(jù)鎖上,在操作他們的時候只允許一個線程去做操作。最終結(jié)果是為了保證cpu計算結(jié)果的正確性。

          對不可重入鎖的理解:

          public class Test{
               Lock lock = new Lock();
               public void methodA(){
                   lock.lock();
                   ...........;
                   methodB();
                   ...........;
                   lock.unlock();
               }
               public void methodB(){
                   lock.lock();
                   ...........;
                   lock.unlock();
               }
          }

          當A方法獲取lock鎖去鎖住一段需要做原子性操作的B方法時,如果這段B方法又需要鎖去做原子性操作,那么A方法就必定要與B方法出現(xiàn)死鎖。這種會出現(xiàn)問題的重入一把鎖的情況,叫不可重入鎖。

          A方法需要等B方法執(zhí)行完才能解鎖,但是B方法想執(zhí)行完代碼又必須要lock鎖來加鎖。A的鎖未解鎖前,其他代碼塊無法使用此鎖來加鎖。這是由這個不可重入鎖決定的。

          不可重入鎖:

          public class Lock{
               private boolean isLocked = false;
               public synchronized void lock() throws InterruptedException{
                   while(isLocked){    
                       wait();
                   }
                   isLocked = true;
               }
               public synchronized void unlock(){
                   isLocked = false;
                   notify();
              }
          }

          那么平時我們又有需要重入一把鎖的需求!!!!比如A方法是個原子性操作,但它有需要調(diào)用B方法的原子性操作,他們還爭搶的是同一個臨界資源,因此需要同一把鎖來加鎖(ps:爭搶同一臨界資源的實質(zhì)就是對同一把鎖的爭搶)

          針對此情況,就有了可重入鎖的概念:

          可重入鎖的實現(xiàn):

          public class Lock{
              boolean isLocked = false;
              Thread  lockedBy = null;
              int lockedCount = 0;
              public synchronized void lock()
                      throws InterruptedException
          {
                  Thread thread = Thread.currentThread();
                  while(isLocked && lockedBy != thread){
                      wait();
                  }
                  isLocked = true;
                  lockedCount++;
                  lockedBy = thread;
              }
              public synchronized void unlock(){
                  if(Thread.currentThread() == this.lockedBy){
                      lockedCount--;
                      if(lockedCount == 0){
                          isLocked = false;
                          notify();
                      }
                  }
              }
          }

          可以看見代碼的核心概念是:

          首先解釋lockedBy:顧名思義,臨界資源被哪個線程鎖住了。

          加鎖時,先獲取當前線程。(識別誰需要鎖)

          Thread thread = Thread.currentThread();

          判斷:當臨界資源已被鎖上,但當前請求鎖的線程又不是之前鎖上臨界資源的線程。那么當前請求鎖的線程需要等待。

          while(isLocked && lockedBy != thread){
                  wait();
          }

          注意上面是個while,并且是個wait,因此當請求線程請求不到鎖的時候,就wait了。

          當時當while不滿足有的3種情況:

          A:當前鎖沒有線程使用.

          B:當前鎖有線程使用,當前請求鎖的線程就是現(xiàn)在正在使用鎖的線程。

          C:當前鎖沒有線程使用,當前請求鎖的線程就是現(xiàn)在正在使用鎖的線程。(不可能出現(xiàn),鎖0沒有被用,哪還有線程使用鎖)

          來看看

          A:沒有線程使用:

          那么:

          isLocked = true;
          lockedCount++;
          lockedBy = thread;

          當前請求鎖的線程先把鎖加上,然后把上鎖次數(shù)+1,然后把自己(本線程)賦值給lockedBy,以說明當前誰用了這把鎖方便之后重入的時候做while判斷。

          再來看解鎖:

          public synchronized void unlock(){
              if(Thread.currentThread() == this.lockedBy){
                  lockedCount--;
                  if(lockedCount == 0){
                      isLocked = false;
                      notify();
                  }
              }
          }

          首先看看要求解鎖的線程是不是當前用鎖的線程。不是則什么也不做。(當然不能隨意讓其他的線程一執(zhí)行unlock代碼就能解鎖使用啊。那這樣相當于誰都有一把鑰匙了,這里這個判斷也就是說明解鎖的必須是加鎖的)

          如果要求解鎖的就是加鎖的線程。

          那么把加鎖次數(shù)減一。

          然后在判斷加鎖次數(shù)有沒有變?yōu)?。

          變?yōu)?說明,這個鎖已經(jīng)完全解鎖了。鎖上標識islocked可以復(fù)位了。

          并且隨機喚醒某個被wait()等待的線程 :notify()


          它和不可重入鎖的設(shè)計不同之處:

          • 不可重入鎖:只判斷這個鎖有沒有被鎖上,只要被鎖上申請鎖的線程都會被要求等待。實現(xiàn)簡單
          • 可重入鎖:不僅判斷鎖有沒有被鎖上,還會判斷鎖是誰鎖上的,當就是自己鎖上的時候,那么他依舊可以再次訪問臨界資源,并把加鎖次數(shù)加一。

          設(shè)計了加鎖次數(shù),以在解鎖的時候,可以確保所有加鎖的過程都解鎖了,其他線程才能訪問。不然沒有加鎖的參考值,也就不知道什么時候解鎖?解鎖多少次?才能保證本線程已經(jīng)訪問完臨界資源了可以喚醒其他線程訪問了。實現(xiàn)相對復(fù)雜。

          總結(jié)

          這個重入的概念就是,拿到鎖的代碼能不能多次以不同的方式訪問臨界資源而不出現(xiàn)死鎖等相關(guān)問題。經(jīng)典之處在于判斷了需要使用鎖的線程是否為加鎖的線程。如果是,則擁有重(chong)入的能力。


          瀏覽 29
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美舔逼视频 | 操逼视频啊啊 | 中文字幕在线一区观看 | 色窝窝视频在线 | 波多野吉衣中文字幕在线 |