欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

???????Java公平鎖和非公平鎖的區(qū)別

 更新時間:2022年05月10日 16:41:49   作者:??Java中文社群????  
本文介紹???????Java公平鎖和非公平鎖區(qū)別,公平鎖是每個線程獲取鎖順序是按照線程訪問鎖的先后順序獲取的,最前面的線程總是最先獲取到鎖;而非公平鎖是每個線程獲取鎖的順序是隨機的,并不會遵循先來先得的規(guī)則,所有線程會競爭獲取鎖,下文內(nèi)容需要的朋友可以參考下

前言:

從公平的角度來說,Java 中的鎖總共可分為兩類:公平鎖和非公平鎖。但公平鎖和非公平鎖有哪些區(qū)別?孰優(yōu)孰劣呢?在 Java 中的應(yīng)用場景又有哪些呢?接下來我們一起來看。

正文

公平鎖:每個線程獲取鎖的順序是按照線程訪問鎖的先后順序獲取的,最前面的線程總是最先獲取到鎖。
非公平鎖:每個線程獲取鎖的順序是隨機的,并不會遵循先來先得的規(guī)則,所有線程會競爭獲取鎖。

 舉個例子:公平鎖就像開車經(jīng)過收費站一樣,所有的車都會排隊等待通過,先來的車先通過,

如下圖所示:

通過收費站的順序也是先來先到,分別是張三、李四、王五,這種情況就是公平鎖。 而非公平鎖相當于,來了一個強行加塞的老司機,它不會準守排隊規(guī)則,來了之后就會試圖強行加塞,如果加塞成功就順利通過,當然也有可能加塞失敗,如果失敗就乖乖去后面排隊,這種情況就是非公平鎖。 

應(yīng)用場景

在 Java 語言中,鎖 synchronized 和 ReentrantLock 默認都是非公平鎖,當然我們在創(chuàng)建 ReentrantLock 時,可以手動指定其為公平鎖,但 synchronized 只能為非公平鎖

 ReentrantLock 默認為非公平鎖可以在它的源碼實現(xiàn)中得到驗證,如下源碼所示: 

 當使用 new ReentrantLock(true) 時,可以創(chuàng)建公平鎖,如下源碼所示: 

公平和非公平鎖代碼演示

接下來我們使用 ReentrantLock 來演示一下公平鎖和非公平鎖的執(zhí)行差異,首先定義一個公平鎖,開啟 3 個線程,每個線程執(zhí)行兩次加鎖和釋放鎖并打印線程名的操作,

如下代碼所示:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockFairTest {
    static Lock lock = new ReentrantLock(true);
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                for (int j = 0; j < 2; j++) {
                    lock.lock();
                    System.out.println("當前線程:" + Thread.currentThread()
                            .getName());
                    lock.unlock();
                }
            }).start();
        }
    }
}

以上程序的執(zhí)行結(jié)果如下圖所示: 

 接下來我們使用非公平鎖來執(zhí)行上面的代碼,具體實現(xiàn)如下:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockFairTest {
    static Lock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                for (int j = 0; j < 2; j++) {
                    lock.lock();
                    System.out.println("當前線程:" + Thread.currentThread()
                            .getName());
                    lock.unlock();
                }
            }).start();
        }
    }
}

以上程序的執(zhí)行結(jié)果如下圖所示: 

從上述結(jié)果可以看出,使用公平鎖線程獲取鎖的順序是:A -> B -> C -> A -> B -> C,也就是按順序獲取鎖。而非公平鎖,獲取鎖的順序是 A -> A -> B -> B -> C -> C,原因是所有線程都爭搶鎖時,因為當前執(zhí)行線程處于活躍狀態(tài),其他線程屬于等待狀態(tài)(還需要被喚醒),所以當前線程總是會先獲取到鎖,所以最終獲取鎖的順序是:A -> A -> B -> B -> C -> C。

執(zhí)行流程分析

公平鎖執(zhí)行流程

獲取鎖時,先將線程自己添加到等待隊列的隊尾并休眠,當某線程用完鎖之后,會去喚醒等待隊列中隊首的線程嘗試去獲取鎖,鎖的使用順序也就是隊列中的先后順序,在整個過程中,線程會從運行狀態(tài)切換到休眠狀態(tài),再從休眠狀態(tài)恢復(fù)成運行狀態(tài),但線程每次休眠和恢復(fù)都需要從用戶態(tài)轉(zhuǎn)換成內(nèi)核態(tài),而這個狀態(tài)的轉(zhuǎn)換是比較慢的,所以公平鎖的執(zhí)行速度會比較慢。

非公平鎖執(zhí)行流程

當線程獲取鎖時,會先通過 CAS 嘗試獲取鎖,如果獲取成功就直接擁有鎖,如果獲取鎖失敗才會進入等待隊列,等待下次嘗試獲取鎖。這樣做的好處是,獲取鎖不用遵循先到先得的規(guī)則,從而避免了線程休眠和恢復(fù)的操作,這樣就加速了程序的執(zhí)行效率。

公平鎖和非公平鎖的性能測試結(jié)果如下:

 從上述結(jié)果可以看出,使用非公平鎖的吞吐率(單位時間內(nèi)成功獲取鎖的平均速率)要比公平鎖高很多。

優(yōu)缺點分析

公平鎖的優(yōu)點是按序平均分配鎖資源,不會出現(xiàn)線程餓死的情況,它的缺點是按序喚醒線程的開銷大,執(zhí)行性能不高。 非公平鎖的優(yōu)點是執(zhí)行效率高,誰先獲取到鎖,鎖就屬于誰,不會“按資排輩”以及順序喚醒,但缺點是資源分配隨機性強,可能會出現(xiàn)線程餓死的情況。

總結(jié)

在 Java 語言中,鎖的默認實現(xiàn)都是非公平鎖,原因是非公平鎖的效率更高,使用 ReentrantLock 可以手動指定其為公平鎖。非公平鎖注重的是性能,而公平鎖注重的是鎖資源的平均分配,所以我們要選擇合適的場景來應(yīng)用二者。

到此這篇關(guān)于Java公平鎖和非公平鎖的區(qū)別的文章就介紹到這了,更多相關(guān)Java 鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java使用Socket類接收和發(fā)送數(shù)據(jù)

    java使用Socket類接收和發(fā)送數(shù)據(jù)

    Socket類是負責(zé)處理客戶端通信的Java類。本文主要是介紹java使用Socket類接收和發(fā)送數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-10-10
  • Spring的@Scope注解作用解析

    Spring的@Scope注解作用解析

    這篇文章主要介紹了Spring的@Scope注解作用解析,@Scope注解用于設(shè)置實例的作用域,默認值是單實例,即當IOC容器啟動后就調(diào)用該方法創(chuàng)建對象放到IOC容器中,以后每次獲取就是直接從容器中獲取,需要的朋友可以參考下
    2023-11-11
  • java如何用遞歸方法求階乘

    java如何用遞歸方法求階乘

    這篇文章主要介紹了java 用遞歸方法求階乘的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 現(xiàn)代高效的java構(gòu)建工具gradle的快速入門

    現(xiàn)代高效的java構(gòu)建工具gradle的快速入門

    和Maven一樣,Gradle只是提供了構(gòu)建項目的一個框架,真正起作用的是Plugin,本文主要介紹了gradle入門,文中通過示例代碼介紹的非常詳細,感興趣的小伙伴們可以參考一下
    2021-11-11
  • SpringBoot四種讀取properties文件的方式(小結(jié))

    SpringBoot四種讀取properties文件的方式(小結(jié))

    這篇文章主要介紹了SpringBoot四種讀取properties文件的方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Java TreeSet類的簡單理解和使用

    Java TreeSet類的簡單理解和使用

    這篇文章主要介紹了Java TreeSet類的簡單理解和使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • 源碼解析Java類加載器

    源碼解析Java類加載器

    這篇文章主要給大家介紹了Java類加載器源碼解析的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java垃圾回收器的方法和原理總結(jié)

    Java垃圾回收器的方法和原理總結(jié)

    本篇文章主要介紹了Java垃圾回收器的方法和原理總結(jié),Java垃圾回收器是Java虛擬機的重要模塊,具有一定的參考價值,有興趣的可以了解一下。
    2016-12-12
  • springboot 使用zookeeper實現(xiàn)分布式隊列的基本步驟

    springboot 使用zookeeper實現(xiàn)分布式隊列的基本步驟

    這篇文章主要介紹了springboot 使用zookeeper實現(xiàn)分布式隊列,通過ZooKeeper的協(xié)調(diào)和同步機制,多個應(yīng)用程序可以共享一個隊列,并按照先進先出的順序處理隊列中的消息,需要的朋友可以參考下
    2023-08-08
  • springboot使用log4j2異步日志提升性能的實現(xiàn)方式

    springboot使用log4j2異步日志提升性能的實現(xiàn)方式

    這篇文章主要介紹了springboot使用log4j2異步日志提升性能,異步日志實現(xiàn)方式:將日志存入一個單獨的隊列中,有一個單獨的線程從隊列中獲取日志并寫入磁盤文件,需要的朋友可以參考下
    2022-05-05

最新評論