最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java自定義互斥鎖的實(shí)現(xiàn)方法示例

 更新時(shí)間:2025年11月15日 12:00:55   作者:va學(xué)弟  
在多線程編程中互斥鎖是確保共享資源安全訪問的重要機(jī)制,這篇文章主要介紹了Java自定義互斥鎖實(shí)現(xiàn)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

今天我們利用AQS實(shí)現(xiàn)一個(gè)基礎(chǔ)的自定義的互斥鎖。

1.AQS

AbstractQueueSynchronizer,簡稱AQS,是 Java 并發(fā)編程的核心基礎(chǔ)框架,它為各種同步器(如ReentrantLockSemaphore、CountDownLatch等)提供了統(tǒng)一的底層實(shí)現(xiàn),解決了并發(fā)場景中線程的同步與協(xié)作問題。它的設(shè)計(jì)思想可以概括為:用一個(gè) volatile 狀態(tài)變量控制同步邏輯,用一個(gè) CLH 隊(duì)列管理等待線程。下面我們簡單介紹一下其核心內(nèi)容。

一、AQS 的核心結(jié)構(gòu)

AQS 的核心由兩部分組成:同步狀態(tài)(State) 和等待隊(duì)列(CLH 隊(duì)列)

1.同步狀態(tài)(State)

        定義:AQS 通過 private volatile int state 變量來維護(hù)同步狀態(tài),該狀態(tài)值的具體語義由實(shí)現(xiàn)類(子類)自行定義。以 ReentrantLock 為例:

  • state = 0 表示鎖未被占有
  • state > 0 表示鎖被持有,數(shù)值代表當(dāng)前線程的重入次數(shù)(線程每次獲取鎖時(shí) state 遞增,釋放鎖時(shí) state 遞減)

2. 等待隊(duì)列(CLH 隊(duì)列)

當(dāng)線程獲取鎖失敗時(shí),AQS 會(huì)將線程封裝成一個(gè)節(jié)點(diǎn)(Node) 加入等待隊(duì)列,這個(gè)隊(duì)列是一個(gè)雙向鏈表,基于 CLH(Craig, Landin, and Hagersten)鎖隊(duì)列改進(jìn)而來。

二、AQS 的核心機(jī)制

AQS(AbstractQueuedSynchronizer)的核心機(jī)制分為獨(dú)占式共享式兩種同步模式,分別對(duì)應(yīng)不同的鎖獲取與釋放邏輯。

1.獨(dú)占式模式(Exclusive)

獨(dú)占式模式下,同一時(shí)刻只有一個(gè)線程能獲取鎖(如 ReentrantLock)。其核心流程如下:

獲取鎖(acquire)

調(diào)用 tryAcquire(int arg):由子類實(shí)現(xiàn),嘗試獲取鎖(如檢查 state 是否為 0,并通過 CAS 修改 state)。若成功,直接返回;若失敗,進(jìn)入后續(xù)步驟。

調(diào)用 addWaiter(Node.EXCLUSIVE):將當(dāng)前線程封裝為獨(dú)占模式的 Node 節(jié)點(diǎn),并加入等待隊(duì)列尾部。

調(diào)用 acquireQueued(Node node, int arg):節(jié)點(diǎn)在隊(duì)列中自旋等待,直到獲取鎖或被取消。在此過程中:

  • 節(jié)點(diǎn)檢查前驅(qū)節(jié)點(diǎn)是否為頭節(jié)點(diǎn):若是,則再次嘗試 tryAcquire;若成功,將自己設(shè)為新頭節(jié)點(diǎn)。
  • 若前驅(qū)節(jié)點(diǎn)狀態(tài)不是 SIGNAL,則將其狀態(tài)改為 SIGNAL(確保前驅(qū)釋放鎖時(shí)能喚醒自己)。
  • 若獲取失敗,通過 LockSupport.park(this) 阻塞當(dāng)前線程。

釋放鎖(release)

調(diào)用 tryRelease(int arg):由子類實(shí)現(xiàn),嘗試釋放鎖(如修改 state 的值)。
若成功,檢查頭節(jié)點(diǎn)的狀態(tài):若為 SIGNAL,則調(diào)用 unparkSuccessor(Node node) 喚醒后繼節(jié)點(diǎn)。
被喚醒的后繼節(jié)點(diǎn)會(huì)重新進(jìn)入自旋,嘗試獲取鎖。

2.共享式模式(Shared)

共享式模式下,同一時(shí)刻多個(gè)線程可獲取鎖(如 Semaphore、CountDownLatch)。其核心流程如下:

獲取鎖(acquireShared)

調(diào)用 tryAcquireShared(int arg):由子類實(shí)現(xiàn),嘗試獲取共享鎖(如檢查 state 是否大于 0)。

若返回值 >=0(成功),直接返回;若 <0(失?。M(jìn)入后續(xù)步驟。

調(diào)用 doAcquireShared(int arg):將線程封裝為共享模式的 Node 節(jié)點(diǎn),加入等待隊(duì)列并自旋等待。

與獨(dú)占式不同,共享模式下,一個(gè)節(jié)點(diǎn)獲取鎖后可能會(huì)喚醒后續(xù)所有共享節(jié)點(diǎn)(如 Semaphorerelease 會(huì)釋放多個(gè)許可)。

釋放鎖(releaseShared)

調(diào)用 tryReleaseShared(int arg):由子類實(shí)現(xiàn),嘗試釋放共享鎖(如增加 state 的值)。
若成功,喚醒后續(xù)等待的共享節(jié)點(diǎn)。

三、AQS 的核心方法

AQS 基于模板方法模式設(shè)計(jì),將同步器的核心邏輯分為兩部分:父類定義的固定流程(模板方法)和子類實(shí)現(xiàn)的定制邏輯(鉤子方法)。

1.模板方法(AQS 已實(shí)現(xiàn))

獨(dú)占式鎖操作

  • acquire(int arg):阻塞式獲取獨(dú)占鎖,忽略中斷。
  • release(int arg):釋放獨(dú)占鎖,喚醒后續(xù)線程。
  • tryAcquireNanos(int arg, long nanosTimeout):支持超時(shí)和中斷的獨(dú)占鎖獲取。

共享式鎖操作

  • acquireShared(int arg):阻塞式獲取共享鎖。
  • releaseShared(int arg):釋放共享鎖,喚醒等待線程。
  • tryAcquireSharedNanos(int arg, long nanosTimeout):支持超時(shí)和中斷的共享鎖獲取。

輔助功能

  • getQueuedThreads():獲取等待隊(duì)列中的線程集合。

2.鉤子方法(子類需重寫)

獨(dú)占式鎖實(shí)現(xiàn)

  • tryAcquire(int arg):定義獨(dú)占鎖的獲取邏輯,返回成功狀態(tài)。
  • tryRelease(int arg):定義獨(dú)占鎖的釋放邏輯,返回成功狀態(tài)。

共享式鎖實(shí)現(xiàn)

  • tryAcquireShared(int arg):定義共享鎖的獲取邏輯,返回剩余可用資源數(shù)。
  • tryReleaseShared(int arg):定義共享鎖的釋放邏輯,返回是否完全釋放。

條件變量支持

  • isHeldExclusively():判斷當(dāng)前線程是否獨(dú)占持有鎖,用于實(shí)現(xiàn) Condition。

通過重寫鉤子方法,子類可靈活實(shí)現(xiàn)公平/非公平鎖、讀寫鎖等同步機(jī)制,而 AQS 負(fù)責(zé)隊(duì)列管理、阻塞喚醒等底層操作。

2.自定義互斥鎖

MLock通過靜態(tài)內(nèi)部類Sync繼承 AQS,并重寫關(guān)鍵方法,實(shí)現(xiàn)了一個(gè)獨(dú)占式非重入鎖(同一線程不能重復(fù)獲取鎖)。

public class MLock {
    private Sync sync = new Sync();
    private static class Sync extends AbstractQueuedLongSynchronizer{

        @Override
        protected boolean tryAcquire(long arg) {
            //利用CAS算法把state變量改成1
            if(compareAndSetState(0,arg)){
                //操作成功后把當(dāng)前線程設(shè)置成獨(dú)占
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;

        }

        @Override
        protected boolean tryRelease(long arg) {
            //清空當(dāng)前線程
            setExclusiveOwnerThread(null);
            setState(arg);
            return true;

        }

        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;

        }
    }

    //加鎖
    public void lock(){
        sync.acquire(1);
    }
    //釋放鎖
    public void unlock(){
        sync.release(0);
    }

}

一、Sync內(nèi)部類(AQS 子類)

Sync 作為鎖的核心實(shí)現(xiàn),重寫了 AQS 中的 3 個(gè)關(guān)鍵方法和 1 個(gè)條件變量方法:

1.tryAcquire(int arg) - 獨(dú)占鎖獲取

執(zhí)行邏輯:當(dāng) state 為 0(未鎖定狀態(tài))時(shí),通過 CAS 操作將其置為 1,并記錄當(dāng)前線程為鎖持有者

2.tryRelease(int arg) - 獨(dú)占鎖釋放

執(zhí)行邏輯:先清除鎖持有者線程信息,再將 state 重置為 0,允許其他線程獲取鎖

3.isHeldExclusively() - 獨(dú)占鎖狀態(tài)檢查

執(zhí)行邏輯:通過檢查 state 是否為 1 來判斷鎖是否被占用(注:簡化實(shí)現(xiàn),實(shí)際還需驗(yàn)證持有者線程)

4.newCondition() - 條件變量創(chuàng)建

功能說明:提供基于鎖的等待/通知機(jī)制,支持 await() 和 signal() 等操作

二、MLock對(duì)外提供的方法

這些方法是鎖的使用接口,內(nèi)部通過調(diào)用Sync(AQS)的方法實(shí)現(xiàn):

  • lock():獲取鎖(阻塞式)

    邏輯:如果tryAcquire成功(獲取鎖),直接返回;否則,當(dāng)前線程會(huì)被加入 AQS 的等待隊(duì)列,進(jìn)入阻塞狀態(tài),直到被喚醒并成功獲取鎖

  • tryLock():嘗試獲取鎖(非阻塞式)                                                                                     
    邏輯:僅嘗試一次獲取鎖,成功返回true,失敗立即返回false,不會(huì)阻塞。

  • unlock():釋放鎖

    邏輯:釋放鎖后,AQS 會(huì)喚醒等待隊(duì)列中的一個(gè)線程,讓其嘗試獲取鎖。

  • newCondition():獲取條件變量用于線程間的協(xié)作(如生產(chǎn)者 - 消費(fèi)者模型),基于當(dāng)前鎖實(shí)現(xiàn)等待 / 通知。

總結(jié) 

到此這篇關(guān)于Java自定義互斥鎖實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)Java自定義互斥鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java List 排序之冒泡排序?qū)嵗a

    java List 排序之冒泡排序?qū)嵗a

    這篇文章主要介紹了java List 排序之冒泡排序?qū)嵗a的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 詳解SpringBoot通用配置文件(不定時(shí)更新)

    詳解SpringBoot通用配置文件(不定時(shí)更新)

    這篇文章主要介紹了SpringBoot通用配置文件詳解(不定時(shí)更新),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • 實(shí)例講解Java 自旋鎖

    實(shí)例講解Java 自旋鎖

    這篇文章主要介紹了Java 自旋鎖的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java并發(fā),感興趣的朋友可以了解下
    2020-09-09
  • Spring中獲取HttpServletRequest的三種方式小結(jié)

    Spring中獲取HttpServletRequest的三種方式小結(jié)

    spring框架web環(huán)境中,獲取HttpServletRequest是常見的操作,本文將為大家詳細(xì)介紹一下Spring中獲取HttpServletRequest的三種方式,有需要的小伙伴可以了解下
    2026-04-04
  • java判斷字符串是否為數(shù)字的方法小結(jié)

    java判斷字符串是否為數(shù)字的方法小結(jié)

    這篇文章主要介紹了java判斷字符串是否為數(shù)字的方法,分別講述了使用Java自帶函數(shù)、正則表達(dá)式及ascii碼三種方法進(jìn)行字符串判斷的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • maven插件spring-boot-starter-tomcat的使用方式

    maven插件spring-boot-starter-tomcat的使用方式

    這篇文章主要介紹了maven插件spring-boot-starter-tomcat的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • spring boot環(huán)境抽象的實(shí)現(xiàn)方法

    spring boot環(huán)境抽象的實(shí)現(xiàn)方法

    在實(shí)際開發(fā)中,開發(fā)人員在編寫springboot的時(shí)候通常要在本地環(huán)境測試然后再部署到Production環(huán)境,這兩種環(huán)境一般來講是不同的,最主要的區(qū)別就是數(shù)據(jù)源的不同。本文主要介紹了這兩種,感興趣的可以了解一下
    2019-04-04
  • 詳解Java中switch的新特性

    詳解Java中switch的新特性

    這篇文章主要介紹了Java中switch的新特性,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 關(guān)于ArrayList初始創(chuàng)建設(shè)定長度問題

    關(guān)于ArrayList初始創(chuàng)建設(shè)定長度問題

    在使用ArrayList時(shí),初始化長度并不等同于直接設(shè)定數(shù)組大小,如通過構(gòu)造函數(shù)指定長度,僅僅是在內(nèi)部開辟了相應(yīng)的存儲(chǔ)空間,并不會(huì)改變ArrayList的實(shí)際元素個(gè)數(shù),即size屬性仍然為0,因此,嘗試直接訪問未實(shí)際添加元素的位置會(huì)引發(fā)異常
    2024-11-11
  • Spring中@Autowired注解作用在方法上和屬性上說明

    Spring中@Autowired注解作用在方法上和屬性上說明

    這篇文章主要介紹了Spring中@Autowired注解作用在方法上和屬性上說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評(píng)論

郑州市| 齐河县| 黄骅市| 瓮安县| 柘城县| 江川县| 方山县| 闵行区| 宁津县| 顺平县| 台安县| 边坝县| 平泉县| 类乌齐县| 云和县| 鹤壁市| 沂源县| 日照市| 太康县| 新竹县| 敦煌市| 信丰县| 辽阳市| 丽江市| 东丰县| 昭平县| 张家港市| 黑龙江省| 永吉县| 平顶山市| 栖霞市| 安龙县| 分宜县| 通辽市| 大余县| 武鸣县| 鹤岗市| 鹤壁市| 东莞市| 大石桥市| 合肥市|