簡單實(shí)現(xiàn)自己的Lock

簡述

我們知道使用ReentrantLock可以實(shí)現(xiàn)同步,保證線程安全,下面我們來簡單實(shí)現(xiàn)自己的Lock

實(shí)現(xiàn)

我們最常使用,也最為重要的就是Lock中的lock()和unlock()方法,因此我們只簡單實(shí)現(xiàn)這兩個(gè)方法,代碼如下

package test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author baipengfei
 * @version 1.0
 * @description TODO
 * @date 19-1-6 上午11:20
 **/
public class MyLock implements Lock {

    private boolean isHoldLock = false;

    /**
     * 同一時(shí)刻,只有一個(gè)線程獲取到鎖
     */
    @Override
    synchronized public void lock() {
        if(isHoldLock){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isHoldLock = true;
    }

    @Override
    synchronized public void unlock() {
        notify();
        isHoldLock = false;
    }

}

當(dāng)?shù)谝粋€(gè)線程進(jìn)行lock時(shí),跳過if,將isHoldLock設(shè)為true,其他線程在lock時(shí)就會(huì)wait等待,直到調(diào)用unlock,notify()將等待的線程喚醒,isHoldLock設(shè)為false是因?yàn)橛锌赡芤粋€(gè)線程速度很快,直接lockunlock一步完成,過程中沒有其他線程調(diào)用lock,所以需要保證結(jié)束后其他線程可以正常調(diào)用lock獲得鎖

缺點(diǎn)

上述代碼簡單實(shí)現(xiàn)了一個(gè)Lock,但是這種Lock不是可重入的,即對(duì)象在一個(gè)線程內(nèi)無法再次獲得自己內(nèi)部的鎖,如下例子

package test;

import java.util.concurrent.locks.Lock;

/**
 * @author baipengfei
 * @version 1.0
 * @description 測試是否可重入
 * @date 19-1-6 上午11:41
 **/
public class ReentryDemo {
    private Lock lock = new MyLock();
    public void methodA(){
        lock.lock();
        System.out.println("進(jìn)入方法A");
        methodB();
        lock.unlock();
    }

    public void methodB(){
        lock.lock();
        System.out.println("進(jìn)入方法B");
        lock.unlock();
    }

    public static void main(String[] args) {
        new ReentryDemo().methodA();
    }
}

methodA等待methodB結(jié)束,而methodB在等待methodA釋放鎖,導(dǎo)致類似與死鎖的情況(其實(shí)不是死鎖)。

解決

下面我們來繼續(xù)改進(jìn)代碼,實(shí)現(xiàn)可重入性

package test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author baipengfei
 * @version 1.0
 * @description TODO
 * @date 19-1-6 上午11:20
 **/
public class MyLock implements Lock {

    private boolean isHoldLock = false;

    private Thread holdLockThread = null;

    private int reentryCount = 0;
    /**
     * 同一時(shí)刻,只有一個(gè)線程獲取到鎖
     */
    @Override
    synchronized public void lock() {
        if(isHoldLock && Thread.currentThread() != holdLockThread){
        //當(dāng)被鎖住時(shí),判斷一下是不是同一線程鎖的,不是就給我等!
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        holdLockThread = Thread.currentThread();
        isHoldLock = true;
        reentryCount ++;
    }

    @Override
    synchronized public void unlock() {
        //判斷當(dāng)前線程是否是持有鎖的線程 是 重入次數(shù)-1 否 不作處理
        if(holdLockThread == Thread.currentThread()){
            reentryCount --;
            if (reentryCount == 0){
                //全部解鎖完畢再喚醒其他線程
                notify();
                isHoldLock = false;
            }
        }


    }
}
  • holdLockThread 用來判斷再次lock時(shí),是否是同一線程進(jìn)行l(wèi)ock,如果不是,就等待吧!
  • reentryCount用來判斷重入次數(shù),因?yàn)橹厝攵啻?,即lock多次后,必須有相同數(shù)量的unlock才算解鎖完畢!其他線程才可以拿到鎖
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容