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

Java并發(fā)編程之ReentrantLock解析

 更新時(shí)間:2023年12月20日 10:00:53   作者:Brain_L  
這篇文章主要介紹了Java并發(fā)編程之ReentrantLock解析,ReentrantLock內(nèi)容定義了一個(gè)抽象類Sync,繼承自AQS,而不是自己去繼承AQS,所有對ReentrantLock的操作都會(huì)轉(zhuǎn)化為對Sync的操作,需要的朋友可以參考下

ReentrantLock

前篇寫了JUC的基礎(chǔ)AQS,其中介紹了它提供的很多模板方法,但是在實(shí)際編程中我們不會(huì)直接使用它,而是會(huì)使用它的各種實(shí)現(xiàn)。

本文將介紹在實(shí)際使用中出現(xiàn)頻率很高的一種并發(fā)鎖——ReentrantLock。

從名字上來看,ReentrantLock具有兩個(gè)特性,一個(gè)是可重入一個(gè)是鎖。

public class ReentrantLock implements Lock, java.io.Serializable {
    private final Sync sync;
    abstract static class Sync extends AbstractQueuedSynchronizer {
        ...
    }
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
        final void lock() {
            acquire(1);
        }
        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    public void lock() {
        sync.lock();
    }
    public void unlock() {
        sync.release(1);
    }
}

ReentrantLock內(nèi)容定義了一個(gè)抽象類Sync,繼承自AQS,而不是自己去繼承AQS,所有對ReentrantLock的操作都會(huì)轉(zhuǎn)化為對Sync的操作。同時(shí)又定義了Sync的兩個(gè)子類FairSync和NonfairSync,分別用于實(shí)現(xiàn)公平鎖和非公平鎖。除非你在生成ReentrantLock時(shí)顯示的指明需要公平鎖,否則默認(rèn)采用非公平鎖。

可重入

先來看下可重入如何實(shí)現(xiàn),以默認(rèn)的非公平鎖舉例。可重入,意味著線程在獲取鎖之后,還可以再次獲取鎖,同樣,獲取了多少次,就要釋放多少次,否則資源釋放不對,別的線程將永遠(yuǎn)無法獲得鎖。

final void lock() {
    //1、CAS將state置為1
    if (compareAndSetState(0, 1))
        //2、設(shè)置自己為獨(dú)占線程
        setExclusiveOwnerThread(Thread.currentThread());
    else
        //3、否則嘗試獲取資源
        acquire(1);
}
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            //1、如果state為0,說明當(dāng)前鎖沒有被占用
            if (c == 0) {
                //2、CAS嘗試將state設(shè)為1
                if (compareAndSetState(0, acquires)) {
                    //3、獲取鎖成功,設(shè)置自己為獨(dú)占線程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //4、如果持有當(dāng)前鎖的線程就是自己
            else if (current == getExclusiveOwnerThread()) {
                //5、那么將state增加acquires
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                //6、更新state,因?yàn)殒i已經(jīng)被自己持有了,所以這里不需要CAS設(shè)置
                setState(nextc);
                return true;
            }
            return false;
}
//AQS
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
}

獲取鎖的過程中,4、5、6三步即實(shí)現(xiàn)了可重入獲取。再看下釋放。

protected final boolean tryRelease(int releases) {
            //1、每次釋放,將state減去釋放數(shù)
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            //2、如果state為0,說明所有資源都已經(jīng)釋放
            if (c == 0) {
                free = true;
                //3、將獨(dú)占線程置空
                setExclusiveOwnerThread(null);
            }
            //4、更新state
            setState(c);
            return free;
        }

同樣,釋放時(shí)需要將獲取的資源依次扣除,什么時(shí)候state減為0了,才算該線程持有的所有資源都釋放掉了。

公平鎖實(shí)現(xiàn)可重入同理,不再贅述。

公平與非公平

那么公平鎖與非公平鎖又有什么區(qū)別呢?

非公平鎖的獲取上面已經(jīng)分析了,來看下公平鎖的獲取,看下有什么不同。

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //1、等待隊(duì)列中是否已經(jīng)有節(jié)點(diǎn)在等待獲取鎖了
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
public final boolean hasQueuedPredecessors() {
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        //2、等待隊(duì)列以后已經(jīng)初始化,并且有別的線程正在入隊(duì)(enq)或者已經(jīng)入隊(duì)
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

公平和非公平的區(qū)別就在于,嘗試獲取鎖前要看下是否有線程已經(jīng)在自己之前就開始等待了,如果沒有才去競爭。通過這種方式保證公平,即先等先得。

公平鎖和非公平鎖哪種性能更好呢,公平鎖雖然能保證等待最久的線程可以先獲得鎖,但是這同時(shí)也以為著每次都會(huì)是不同的線程獲取鎖,每次都要進(jìn)行線程切換。《Java并發(fā)編程的藝術(shù)》進(jìn)行了測試,表明非公平鎖雖然可能造成某些線程一直獲取不到鎖,但是可以提高整體的吞吐量,所以ReentrantLock將其作為了默認(rèn)實(shí)現(xiàn)。如果是需要保證這種先等先得的特性,也可以使用公平鎖。

與synchronized對比

ReentrantLock在加鎖和內(nèi)存語義上提供了與synchronized相同的功能,此外還提供了定時(shí)、可中斷、公平性等特性。

JDK5時(shí),ReentrantLock的性能要遠(yuǎn)優(yōu)于synchronized,但是JDK6引入了synchronized的鎖優(yōu)化,兩者之間的差別并沒有那么大了。

除非需要一些高級(jí)功能,如可定時(shí)、可輪詢、可中斷、公平性等,才使用ReentrantLock,否則應(yīng)該優(yōu)先使用synchronized,畢竟大部分人都用習(xí)慣了,而且使用簡單。

到此這篇關(guān)于Java并發(fā)編程之ReentrantLock解析的文章就介紹到這了,更多相關(guān)Java的ReentrantLock內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Java語言在窗體上實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲的完整步驟

    基于Java語言在窗體上實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲的完整步驟

    這篇文章主要給大家介紹了基于Java語言在窗體上實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲的完整步驟,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • SpringBoot整合Javamail實(shí)現(xiàn)郵件發(fā)送的詳細(xì)過程

    SpringBoot整合Javamail實(shí)現(xiàn)郵件發(fā)送的詳細(xì)過程

    日常開發(fā)過程中,我們經(jīng)常需要使用到郵件發(fā)送任務(wù),比方說驗(yàn)證碼的發(fā)送、日常信息的通知等,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合Javamail實(shí)現(xiàn)郵件發(fā)送的詳細(xì)過程,需要的朋友可以參考下
    2022-10-10
  • java生成圖片驗(yàn)證碼實(shí)例代碼

    java生成圖片驗(yàn)證碼實(shí)例代碼

    這篇文章主要介紹了java生成圖片驗(yàn)證碼實(shí)例代碼,驗(yàn)證碼的種類有很多,問題驗(yàn)證、短信驗(yàn)證還有常見的圖片驗(yàn)證,本文就為大家介紹生成圖片驗(yàn)證碼最簡單方法,感興趣的小伙伴們可以參考一下
    2016-04-04
  • springboot根據(jù)sessionId查詢session方式

    springboot根據(jù)sessionId查詢session方式

    文章介紹了通過保存session和sessionId進(jìn)行跨域問題的校驗(yàn),提出創(chuàng)建保存session的類,建立監(jiān)聽器監(jiān)聽session的創(chuàng)建和銷毀,并在啟動(dòng)類上添加注解@ServletComponentScan以掃描SessionListener
    2026-04-04
  • JSON字符串中獲取一個(gè)指定字段的值四種方式

    JSON字符串中獲取一個(gè)指定字段的值四種方式

    在Java開發(fā)中,我們經(jīng)常會(huì)遇到需要從JSON數(shù)據(jù)中提取特定字段值的情況,這篇文章主要給大家介紹了關(guān)于JSON字符串中獲取一個(gè)指定字段的值四種方式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • Java處理Markdown格式轉(zhuǎn)換為Word文檔

    Java處理Markdown格式轉(zhuǎn)換為Word文檔

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)處理Markdown格式轉(zhuǎn)換為Word文檔,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下
    2025-03-03
  • Java實(shí)戰(zhàn)項(xiàng)目之校園跑腿管理系統(tǒng)的實(shí)現(xiàn)

    Java實(shí)戰(zhàn)項(xiàng)目之校園跑腿管理系統(tǒng)的實(shí)現(xiàn)

    只有理論是不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+Springboot+vue+maven+elementui+mysql實(shí)現(xiàn)一個(gè)校園跑腿管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平
    2022-01-01
  • 基于Java實(shí)現(xiàn)文件和base64字符串轉(zhuǎn)換

    基于Java實(shí)現(xiàn)文件和base64字符串轉(zhuǎn)換

    這篇文章主要介紹了基于Java實(shí)現(xiàn)文件和base64字符串轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • spring使用@Async注解導(dǎo)致循環(huán)依賴問題異常的排查記錄

    spring使用@Async注解導(dǎo)致循環(huán)依賴問題異常的排查記錄

    這篇文章主要介紹了spring使用@Async注解導(dǎo)致循環(huán)依賴問題異常的排查記錄,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java數(shù)組的定義與使用

    Java數(shù)組的定義與使用

    數(shù)組是有序的元素序列,若將有限個(gè)類型相同的變量的集合命名,那么這個(gè)名稱為數(shù)組名。本文通過代碼示例詳細(xì)介紹了Java數(shù)組的定義和使用,對學(xué)習(xí)或工作有一定的幫助,需要的小伙伴歡迎閱讀
    2023-04-04

最新評論

邵武市| 保康县| 台前县| 丘北县| 磐石市| 修武县| 团风县| 茌平县| 普陀区| 湾仔区| 苏尼特左旗| 蒙城县| 靖州| 定西市| 茶陵县| 吉安县| 博兴县| 青田县| 石景山区| 营山县| 泊头市| 绥化市| 黄梅县| 松滋市| 龙胜| 五寨县| 固镇县| 明光市| 四子王旗| 乌拉特前旗| 永德县| 四川省| 久治县| 湖北省| 巴塘县| 邢台县| 南靖县| 图片| 安泽县| 禄丰县| 邢台县|