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

java?ReentrantLock并發(fā)鎖使用詳解

 更新時間:2022年10月12日 17:09:21   作者:Jony_zhang  
這篇文章主要為大家介紹了java?ReentrantLock并發(fā)鎖使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

一、ReentrantLock是什么

ReentrantLock是一種基于AQS框架的應(yīng)用實現(xiàn),是JDK中的一種線程并發(fā)訪問的同步手段,它的功能類似于synchronized是一種互斥鎖,可以保證線程安全。

相對于 synchronized, ReentrantLock具備如下特點:

  • 可中斷
  • 可以設(shè)置超時時間
  • 可以設(shè)置為公平鎖
  • 支持多個條件變量
  • 與 synchronized 一樣,都支持可重入

進入源碼可以看到,其實現(xiàn)了公平鎖和非公平鎖

內(nèi)部實現(xiàn)了加鎖的操作,并且支持重入鎖。不用我們再重寫

解鎖操作

1-1、ReentrantLock和synchronized區(qū)別

synchronized和ReentrantLock的區(qū)別:

  • synchronized是JVM層次的鎖實現(xiàn),ReentrantLock是JDK層次的鎖實現(xiàn);
  • synchronized的鎖狀態(tài)是無法在代碼中直接判斷的,但是ReentrantLock可以通過ReentrantLock#isLocked判斷;
  • synchronized是非公平鎖,ReentrantLock是可以是公平也可以是非公平的;
  • synchronized是不可以被中斷的,而ReentrantLock#lockInterruptibly方法是可以被中斷的;
  • 在發(fā)生異常時synchronized會自動釋放鎖,而ReentrantLock需要開發(fā)者在finally塊中顯示釋放鎖;
  • ReentrantLock獲取鎖的形式有多種:如立即返回是否成功的tryLock(),以及等待指定時長的獲取,更加靈活;
  • synchronized在特定的情況下對于已經(jīng)在等待的線程是后來的線程先獲得鎖(回顧一下sychronized的喚醒策略),而ReentrantLock對于已經(jīng)在等待的線程是先來的線程先獲得鎖;

1-2、ReentrantLock的使用

1-2-1、ReentrantLock同步執(zhí)行,類似synchronized

使用ReentrantLock需要注意的是:一定要在finally中進行解鎖,方式業(yè)務(wù)拋出異常,無法解鎖

public class ReentrantLockDemo {
    private static  int sum = 0;
    private static ReentrantLock lock=new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            Thread thread = new Thread(()->{
                //加鎖
                lock.lock();
                try {
                    // 臨界區(qū)代碼
                    // TODO 業(yè)務(wù)邏輯:讀寫操作不能保證線程安全
                    for (int j = 0; j < 10000; j++) {
                        sum++;
                    }
                } finally {
                    // 解鎖--一定要在finally中解鎖,防止業(yè)務(wù)代碼異常,無法釋放鎖
                    lock.unlock();
                }
            });
            thread.start();
        }
        Thread.sleep(2000);
        System.out.println(sum);
    }
}

測試結(jié)果:

1-2-2、可重入鎖

可重入鎖就是 A(加鎖)-->調(diào)用--->B(加鎖)-->調(diào)用-->C(加鎖),從A到C即使B/C都有加鎖,也可以進入

@Slf4j
public class ReentrantLockDemo2 {
    public static ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) {
        method1();
    }
    public static void method1() {
        lock.lock();
        try {
            log.debug("execute method1");
            method2();
        } finally {
            lock.unlock();
        }
    }
    public static void method2() {
        lock.lock();
        try {
            log.debug("execute method2");
            method3();
        } finally {
            lock.unlock();
        }
    }
    public static void method3() {
        lock.lock();
        try {
            log.debug("execute method3");
        } finally {
            lock.unlock();
        }
    }
}

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

1-2-3、鎖中斷

可以使用lockInterruptibly來進行鎖中斷

lockInterruptibly()方法能夠中斷等待獲取鎖的線程。當兩個線程同時通過lock.lockInterruptibly()獲取某個鎖時,假若此時線程A獲取到了鎖,而線程B只有等待,那么對線程B調(diào)用threadB.interrupt()方法能夠中斷線程B的等待過程。

public class ReentrantLockDemo3 {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Thread t1 = new Thread(() -> {
            log.debug("t1啟動...");
            try {
                lock.lockInterruptibly();
                try {
                    log.debug("t1獲得了鎖");
                } finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                log.debug("t1等鎖的過程中被中斷");
            }
        }, "t1");
        lock.lock();
        try {
            log.debug("main線程獲得了鎖");
            t1.start();
            //先讓線程t1執(zhí)行
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t1.interrupt();
            log.debug("線程t1執(zhí)行中斷");
        } finally {
            lock.unlock();
        }
    }
}

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

1-2-4、獲得鎖超時失敗

可以讓線程等待指定的時間,如果還未獲取鎖則進行失敗處理。

如下代碼,首先讓主線程獲得鎖,然后讓子線程啟動嘗試獲取鎖,但是由于主線程獲取鎖之后,讓線程等待了2秒,而子線程獲得鎖的超時時間只有1秒,如果未獲得鎖,則進行return失敗處理

public class ReentrantLockDemo4 {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Thread t1 = new Thread(() -> {
            log.debug("t1啟動...");
            //超時
            try {
                if (!lock.tryLock(1, TimeUnit.SECONDS)) {
                    log.debug("等待 1s 后獲取鎖失敗,返回");
                    return;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                return;
            }
            try {
                log.debug("t1獲得了鎖");
            } finally {
                lock.unlock();
            }
        }, "t1");
        lock.lock();
        try {
            log.debug("main線程獲得了鎖");
            t1.start();
            //先讓線程t1執(zhí)行
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            lock.unlock();
        }
    }
}

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

1-2-5、公平鎖

ReentrantLock 默認是不公平的

首先啟動500次for循環(huán)創(chuàng)建500個線程,然后進行加鎖操作,并同時啟動了。這樣這500個線程就依次排隊等待加鎖的處理

下面500個線程也是等待加鎖操作

如果使用公平鎖,下面500的線程只有等上面500個線程運行完成之后才能獲得鎖。

@Slf4j
public class ReentrantLockDemo5 {
    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock(true); //公平鎖
        for (int i = 0; i < 500; i++) {
            new Thread(() -> {
                lock.lock();
                try {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    log.debug(Thread.currentThread().getName() + " running...");
                } finally {
                    lock.unlock();
                }
            }, "t" + i).start();
        }
        // 1s 之后去爭搶鎖
        Thread.sleep(1000);
        for (int i = 0; i < 500; i++) {
            new Thread(() -> {
                lock.lock();
                try {
                    log.debug(Thread.currentThread().getName() + " running...");
                } finally {
                    lock.unlock();
                }
            }, "強行插入" + i).start();
        }
    }
}

測試結(jié)果(后進入的線程都在等待排隊)

使用非公平鎖的情況下,就可以看到下面500線程有些線程就可以搶占鎖了

那ReentrantLock為什么默認使用非公平鎖呢?實際上就是為了提高性能,如果使用公平鎖,當前鎖對象釋放之后,還需要去隊列中獲取第一個排隊的線程,然后進行加鎖處理。而非公平鎖,可能再當前對象釋放鎖之后,正好有新的線程在獲取鎖,這樣就可以直接進行加鎖操作,不必再去隊列中讀取。

以上就是java ReentrantLock并發(fā)鎖使用詳解的詳細內(nèi)容,更多關(guān)于java ReentrantLock并發(fā)鎖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaSE正則表達式用法總結(jié)大全

    JavaSE正則表達式用法總結(jié)大全

    正則表達式就是由一些特定的字符組成,代表的是一個規(guī)則,這篇文章主要介紹了JavaSE正則表達式用法的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-06-06
  • springmvc接口接收參數(shù)與請求參數(shù)格式的整理

    springmvc接口接收參數(shù)與請求參數(shù)格式的整理

    這篇文章主要介紹了springmvc接口接收參數(shù)與請求參數(shù)格式的整理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Spring Boot Actuator執(zhí)行器運行原理詳解

    Spring Boot Actuator執(zhí)行器運行原理詳解

    這篇文章主要介紹了Spring Boot Actuator執(zhí)行器運行原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • springboot之Validation參數(shù)校驗詳細解讀

    springboot之Validation參數(shù)校驗詳細解讀

    這篇文章主要介紹了springboot之Validation參數(shù)校驗詳細解讀,本篇是關(guān)于springboot的參數(shù)校驗知識,當然也適用其它java應(yīng)用,讀完本篇將學會基本的參數(shù)校驗,自定義參數(shù)校驗和分組參數(shù)校驗,需要的朋友可以參考下
    2023-10-10
  • Spring Boot 利用WebUploader進行文件上傳功能

    Spring Boot 利用WebUploader進行文件上傳功能

    本文的重點是給大家介紹在Spring Boot項目中利用WebUploader如何進行文件上傳,本文通過示例代碼給大家介紹,需要的朋友參考下吧
    2018-03-03
  • springboot關(guān)于容器啟動事件總結(jié)

    springboot關(guān)于容器啟動事件總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于springboot容器啟動事件相關(guān)知識點,需要的朋友們學習下。
    2019-10-10
  • Netty啟動步驟綁定端口示例方法源碼分析

    Netty啟動步驟綁定端口示例方法源碼分析

    這篇文章主要介紹了Netty啟動步驟綁定端口源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • SpringSecurity框架下實現(xiàn)CSRF跨站攻擊防御的方法

    SpringSecurity框架下實現(xiàn)CSRF跨站攻擊防御的方法

    CSRF是一種網(wǎng)絡(luò)攻擊方式,也可以說是一種安全漏洞,這種安全漏洞在web開發(fā)中廣泛存在。這篇文章主要介紹了SpringSecurity框架下實現(xiàn)CSRF跨站攻擊防御,需要的朋友可以參考下
    2019-12-12
  • 使用SpringMVC在redirect重定向的時候攜帶參數(shù)的問題

    使用SpringMVC在redirect重定向的時候攜帶參數(shù)的問題

    這篇文章主要介紹了使用SpringMVC在redirect重定向的時候攜帶參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Sentinel中實現(xiàn)限流的兩種方法

    Sentinel中實現(xiàn)限流的兩種方法

    本文給大家介紹了Sentinel中實現(xiàn)限流的兩種方法,限流是一種通過控制系統(tǒng)對外提供的資源、服務(wù)或接口的訪問數(shù)量或速率,以保護系統(tǒng)免受過載的一種策略,需要的朋友可以參考下
    2024-02-02

最新評論

秀山| 崇文区| 海丰县| 神农架林区| 广东省| 灵山县| 七台河市| 崇阳县| 临泽县| 凉城县| 手游| 呼玛县| 资兴市| 时尚| 孝义市| 宁城县| 施秉县| 泽库县| 郸城县| 咸丰县| 饶阳县| 宝兴县| 贵德县| 南投县| 铁力市| 北川| 海城市| 集贤县| 策勒县| 南阳市| 松江区| 吉安市| 阳泉市| 闽清县| 梧州市| 泸州市| 仙桃市| 曲沃县| 禹州市| 巴彦淖尔市| 景宁|