可重入鎖 - ReentrantLock

重進(jìn)入是指任意線程在獲取鎖以后,能夠再次獲取該鎖而不會(huì)被鎖所阻塞
大白話就是說(shuō)一個(gè)加鎖的方法里面調(diào)用同一對(duì)象中另外一個(gè)加鎖的方法可以直接獲取鎖,不會(huì)阻塞

閱讀完后可以大概了解一下ReentrantLock是個(gè)什么東東,然后最好自己去擼下源碼,看下原理。

構(gòu)造

//創(chuàng)建一個(gè)非公平獲取鎖的ReentrantLock實(shí)例
ReentrantLock()
//使用給定的公平性策略創(chuàng)建ReentrantLock實(shí)例
//true : 公平獲取鎖
//false: 非公平獲取鎖 (默認(rèn)) 
ReentrantLock(boolean fair)

ReentrantLock 方法

類型 方法 描述
int getHoldCount() 當(dāng)前線程對(duì)此鎖的持有數(shù),如果當(dāng)前線程不持有此鎖,則為零
protected Thread getOwner() 返回當(dāng)前擁有此鎖的線程,如果不擁有該鎖,則返回null
protected Collection<Thread> getQueuedThreads() 返回一個(gè)包含可能正在等待獲取此鎖的線程的集合
int getQueueLength() 返回等待獲取此鎖的線程數(shù)
protected Collection<Thread> getWaitingThreads(Condition condition) 返回一個(gè)集合,該集合包含那些可能正在等待與此鎖關(guān)聯(lián)的給定條件的線程
int getWaitQueueLength(Condition condition) 返回等待與此鎖關(guān)聯(lián)的給定條件的線程數(shù)
boolean hasQueuedThread(Thread thread) 查詢給定線程是否正在等待獲取此鎖
boolean hasQueuedThreads() 查詢是否有任何線程正在等待獲取此鎖
boolean hasWaiters(Condition condition) 查詢是否有線程正在等待與此鎖關(guān)聯(lián)的給定條件
boolean isFair() 獲取公平性策略,公平鎖返回ture,反之返回false
boolean isHeldByCurrentThread() 查詢此鎖是否由當(dāng)前線程持有
boolean isLocked() 查詢是否有線程持有鎖
void lockInterruptibly() 獲取鎖,除非當(dāng)前線程被中斷
Condition newCondition() 返回用于此鎖實(shí)例的條件實(shí)例
String toString() 返回標(biāo)識(shí)此鎖的字符串及其鎖定狀態(tài)
boolean tryLock() 僅在調(diào)用時(shí)其他線程未持有該鎖時(shí)才獲取該鎖
boolean tryLock(long timeout, TimeUnit unit) 如果在給定的等待時(shí)間內(nèi)沒有被另一個(gè)線程持有,并且當(dāng)前線程沒有被中斷,則獲取該鎖
void unlock() 釋放鎖

例子

package com.sy.thread.example;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Description: thread
 *
 * @author songyu
 */
public class ReentrantLockTest {
    static DateTimeFormatter fmTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    static ReentrantLock lock = new ReentrantLock();
    public static void test(int i) {
        //獲取鎖
        lock.lock();
        try {
            LocalDateTime now = LocalDateTime.now();
            System.out.println( now.format(fmTime) + " 第" + i + "個(gè)線程獲取到鎖,等待5秒,釋放鎖");
            Thread.sleep(5000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //釋放鎖
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        //連續(xù)調(diào)用五次test()方法
        for (int i = 1; i <= 5; i++ ) {
            test(i);
        }
    }
}

執(zhí)行結(jié)果

2020-07-10 17:24:50 第1個(gè)線程獲取到鎖,等待5秒,釋放鎖
2020-07-10 17:24:55 第2個(gè)線程獲取到鎖,等待5秒,釋放鎖
2020-07-10 17:25:00 第3個(gè)線程獲取到鎖,等待5秒,釋放鎖
2020-07-10 17:25:05 第4個(gè)線程獲取到鎖,等待5秒,釋放鎖
2020-07-10 17:25:10 第5個(gè)線程獲取到鎖,等待5秒,釋放鎖

例子 - 重進(jìn)入

package com.sy.thread.example;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Description: thread
 *
 * @author songyu
 */
public class ReentrantLockTest1 {
    static DateTimeFormatter fmTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    static ReentrantLock lock = new ReentrantLock(){};

    public static void test(int i) {
        System.out.println("");
        lock.lock();
        try {
            LocalDateTime now = LocalDateTime.now();
            System.out.println( now.format(fmTime) + " 第" + i + "次調(diào)用進(jìn)入方法,等待5秒,釋放鎖");
            //調(diào)用另一個(gè)需要獲取鎖的方法
            test2(i);
            Thread.sleep(5000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void test2(int i) {
        lock.lock();
        try {
            LocalDateTime now2 = LocalDateTime.now();
            //獲取當(dāng)前線程對(duì)鎖的持有數(shù)
            int holdCount = lock.getHoldCount();
            System.out.println( now2.format(fmTime) + " 第" + i + "次調(diào)用 - - 調(diào)用第二個(gè)需要獲取鎖的方法 成功再次獲取鎖,未阻塞");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            test(i);
        }
    }
}

執(zhí)行結(jié)果

2020-07-10 18:14:04 第0次調(diào)用進(jìn)入方法,等待5秒,釋放鎖
2020-07-10 18:14:04 第0次調(diào)用 - - 調(diào)用第二個(gè)需要獲取鎖的方法 成功再次獲取鎖,未阻塞

2020-07-10 18:14:09 第1次調(diào)用進(jìn)入方法,等待5秒,釋放鎖
2020-07-10 18:14:09 第1次調(diào)用 - - 調(diào)用第二個(gè)需要獲取鎖的方法 成功再次獲取鎖,未阻塞

2020-07-10 18:14:14 第2次調(diào)用進(jìn)入方法,等待5秒,釋放鎖
2020-07-10 18:14:14 第2次調(diào)用 - - 調(diào)用第二個(gè)需要獲取鎖的方法 成功再次獲取鎖,未阻塞

2020-07-10 18:14:19 第3次調(diào)用進(jìn)入方法,等待5秒,釋放鎖
2020-07-10 18:14:19 第3次調(diào)用 - - 調(diào)用第二個(gè)需要獲取鎖的方法 成功再次獲取鎖,未阻塞

2020-07-10 18:14:24 第4次調(diào)用進(jìn)入方法,等待5秒,釋放鎖
2020-07-10 18:14:24 第4次調(diào)用 - - 調(diào)用第二個(gè)需要獲取鎖的方法 成功再次獲取鎖,未阻塞

線程重復(fù)獲取了N次鎖,只有當(dāng)線程釋放了N次鎖以后,其它的線程才能獲取鎖。

?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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