1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 5532字,需瀏覽 12分鐘

         ·

        2021-07-03 14:37

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

        對(duì)不可重入鎖的理解:

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

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

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

        不可重入鎖:

        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();
            }
        }

        那么平時(shí)我們又有需要重入一把鎖的需求!?。。”热鏏方法是個(gè)原子性操作,但它有需要調(diào)用B方法的原子性操作,他們還爭(zhēng)搶的是同一個(gè)臨界資源,因此需要同一把鎖來(lái)加鎖(ps:爭(zhēng)搶同一臨界資源的實(shí)質(zhì)就是對(duì)同一把鎖的爭(zhēng)搶?zhuān)?/p>

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

        可重入鎖的實(shí)現(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();
                    }
                }
            }
        }

        可以看見(jiàn)代碼的核心概念是:

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

        加鎖時(shí),先獲取當(dāng)前線程。(識(shí)別誰(shuí)需要鎖)

        Thread thread = Thread.currentThread();

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

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

        注意上面是個(gè)while,并且是個(gè)wait,因此當(dāng)請(qǐng)求線程請(qǐng)求不到鎖的時(shí)候,就wait了。

        當(dāng)時(shí)當(dāng)while不滿(mǎn)足有的3種情況:

        A:當(dāng)前鎖沒(méi)有線程使用.

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

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

        來(lái)看看

        A:沒(méi)有線程使用:

        那么:

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

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

        再來(lái)看解鎖:

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

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

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

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

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

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

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


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

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

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

        總結(jié)

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


        瀏覽 29
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            香蕉久久夜色精品国产使用方法 | 免费观看成人AV | 交换做爰在线观看 | 欧美三级成人网站 | 69视频网站 | 亚洲AV伊人久久青青草原视色 | 日韩精品一区二区三区色欲AV | 99精品国产综合久久久久五月天 | 欧美做爰BBB性BBBBB丨D | 日韩久久久久久久 |