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

Java 讀寫鎖源碼分析

 更新時(shí)間:2021年01月30日 10:06:29   作者:消滅知識(shí)盲區(qū)  
這篇文章主要介紹了Java 讀寫鎖的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下

前言

在實(shí)際項(xiàng)目中,比如我們有一個(gè)共享資源文件,我們程序會(huì)會(huì)同時(shí)并發(fā)的去讀、寫這個(gè)共享資源文件,那怎么能保證在高并發(fā)場(chǎng)景下安全、高效讀寫呢?OK,看了下文便知

提示:以下是本篇文章正文內(nèi)容,案例僅供參考

一、技術(shù)介紹

1.ReentranReadWriteLock是什么?

ReadWriteLock提供了readLock和writeLock兩種鎖的操作機(jī)制,一個(gè)是讀鎖,一個(gè)是寫鎖,而它的實(shí)現(xiàn)類就是ReentranReadWriteLock

讀鎖可以在沒(méi)有寫鎖的時(shí)候被多個(gè)線程同時(shí)持有,寫鎖是獨(dú)占的(排他的)。這意味著每次只能有一個(gè)線程寫,但可以多個(gè)線程并發(fā)地讀。

理論上,讀寫鎖比互斥鎖允許對(duì)于共享數(shù)據(jù)更大程度的并發(fā)。與互斥鎖相比,讀寫鎖是否能夠提高性能取決于讀寫數(shù)據(jù)的頻率、讀取和寫入操作的持續(xù)時(shí)間、以及讀線程和寫線程之間的競(jìng)爭(zhēng)。

二、源碼分析

1.ReadLock

直接看ReadLock源碼

可以看到ReadLock的lock操作實(shí)際實(shí)現(xiàn)對(duì)應(yīng)Sync的 tryAcquireShared 方法,我們點(diǎn)進(jìn)去看看

  1. 如果另一個(gè)線程持有寫鎖,則失敗。
  2. readerShouldBlock():讀鎖是否需要等待(公平鎖原則); r < MAX_COUNT:持有線程小于最大數(shù) ;compareAndSetState(c, c + SHARED_UNIT):設(shè)置讀取鎖狀態(tài);整體意思就是讀線程是否應(yīng)該被阻塞、并且小于最大值、并且比較設(shè)置成功
  3. else判斷里讀鎖數(shù)量不為0并且不為當(dāng)前線程,獲取計(jì)數(shù)器并且+1
  4. 最后的這行方法執(zhí)行是由于線程顯然不符合條件,或者CAS失敗或計(jì)數(shù)飽和,使用完整版本的獲取,這里面的方法可處理CAS miss 和tryAcquireShared中未處理的可重入讀

2.WriteLock

再接著看WriteLock源碼

exclusiveCount方法的作用是將同步變量與0xFFFF做&運(yùn)算,計(jì)算結(jié)果就是寫鎖的數(shù)量,因此w的值的含義就是寫鎖的數(shù)量 如果c不為0就表示鎖被占用了,占用的是寫鎖還是讀鎖呢?這個(gè)時(shí)候就需要根據(jù)w的值來(lái)判斷了。 如果c等于0就表示此時(shí)鎖還沒(méi)有被任何線程占用,那就讓線程直接去嘗試獲取鎖.

如果w為0,說(shuō)明寫鎖數(shù)量為0,而此時(shí)又因?yàn)閏不等于0,說(shuō)明鎖被占用,但是不是寫鎖,那么此時(shí)鎖的狀態(tài)一定是讀鎖,既然是讀鎖狀態(tài),那么寫鎖此時(shí)來(lái)獲取鎖時(shí),就肯定失敗,因此當(dāng)w等于0時(shí),tryAcquire方法返回false。

如果w不為0,說(shuō)明此時(shí)鎖的狀態(tài)時(shí)寫鎖,接著進(jìn)行current != getExclusiveOwnerThread()判斷,判斷持有鎖的線程是否是當(dāng)前線程

如果不是當(dāng)前線程,那么tryAcquire()返回false;如果是當(dāng)前線程,那么就進(jìn)行后面的邏輯。為什么是當(dāng)前線程持有鎖,就還能執(zhí)行后面的邏輯呢?那是因?yàn)樽x寫鎖是可重入的。

三、單元測(cè)試

OK,不廢話,接下來(lái)上簡(jiǎn)單直接的單元測(cè)試

package com.hyh.core.test;

import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 可重入讀寫鎖 TEST
 *
 * @Author: heyuhua
 * @Date: 2021/1/28 14:14
 */
public class ReentranReadWriteLockTest {

  ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
  Lock readLock = reentrantReadWriteLock.readLock();
  Lock writeLock = reentrantReadWriteLock.writeLock();


  @Test
  public void test() throws InterruptedException {
    ExecutorService threadPool = Executors.newFixedThreadPool(10);
    for (int i = 0; i < 5; i++) {
      threadPool.execute(() -> {
        readLock();
      });
      threadPool.execute(() -> {
        writeLock();
      });
    }
    threadPool.shutdown();
    TimeUnit.SECONDS.sleep(10);
  }

  private void readLock() {
    readLock.lock();
    try {
      System.out.println(Thread.currentThread().getName() + "-獲取讀鎖...");
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      System.out.println(Thread.currentThread().getName() + "-釋放讀鎖...");
      readLock.unlock();
    }
  }

  private void writeLock() {
    writeLock.lock();
    try {
      System.out.println(Thread.currentThread().getName() + "-獲取寫鎖...");
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      System.out.println(Thread.currentThread().getName() + "-釋放寫鎖...");
      writeLock.unlock();
    }
  }


}

這里模擬5個(gè)讀和5個(gè)寫的并發(fā)情況,馬上看下執(zhí)行結(jié)果

可以看到多個(gè)線程都可以同時(shí)獲得讀鎖,而寫鎖必須等讀鎖釋放了后才能獲取,同樣的讀鎖必須等寫鎖釋放了后才能獲取

總結(jié)

讀寫鎖總結(jié)一句話:讀讀共享、寫寫互斥、讀寫互斥。

讀寫鎖的適用場(chǎng)合:相比于 ReentrantLock 適用于一般場(chǎng)合,ReadWriteLock 適用讀多寫少的場(chǎng)景,合理使用可以進(jìn)一步提高并發(fā)

作者寄語(yǔ)

是不是感覺(jué)很簡(jiǎn)單?更多用法請(qǐng)點(diǎn)擊下方查看源碼,關(guān)注我?guī)憬颐馗喔呒?jí)用法

源碼地址:點(diǎn)此查看源碼

以上就是Java 讀寫鎖源碼分析的詳細(xì)內(nèi)容,更多關(guān)于Java 讀寫鎖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺析Java中Split函數(shù)的用法技巧

    淺析Java中Split函數(shù)的用法技巧

    在java.lang包中也有String.split()方法,與.net的類似,都是返回是一個(gè)字符型數(shù)組,但使用過(guò)程中還有一些小技巧。以下我就為大家介紹,需要的朋友可以參考下
    2013-07-07
  • 基于Java制作一個(gè)燈謎猜猜樂(lè)游戲

    基于Java制作一個(gè)燈謎猜猜樂(lè)游戲

    中秋佳節(jié),是我國(guó)傳統(tǒng)的重大節(jié)日之一,全國(guó)各地為了增強(qiáng)過(guò)節(jié)的氣氛,都有許多傳統(tǒng)的中秋活動(dòng),比如猜燈謎,所以本文就來(lái)用Java制作一個(gè)燈謎猜猜樂(lè)游戲,感興趣的可以了解下
    2023-09-09
  • Spring配置使用之Bean生命周期詳解

    Spring配置使用之Bean生命周期詳解

    這篇文章主要介紹了Spring配置使用之Bean生命周期詳解,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • 深入理解hibernate的三種狀態(tài)

    深入理解hibernate的三種狀態(tài)

    本篇文章主要介紹了深入理解hibernate的三種狀態(tài) ,主要包括了transient(瞬時(shí)狀態(tài)),persistent(持久化狀態(tài))以及detached(離線狀態(tài)),有興趣的同學(xué)可以了解一下
    2017-05-05
  • 詳解如何用SpringBoot 2.3.0.M1創(chuàng)建Docker映像

    詳解如何用SpringBoot 2.3.0.M1創(chuàng)建Docker映像

    這篇文章主要介紹了詳解如何用SpringBoot 2.3.0.M1創(chuàng)建Docker映像,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • springboot配置kafka批量消費(fèi),并發(fā)消費(fèi)方式

    springboot配置kafka批量消費(fèi),并發(fā)消費(fèi)方式

    文章介紹了如何在Spring Boot中配置Kafka進(jìn)行批量消費(fèi),并發(fā)消費(fèi),需要注意的是,并發(fā)量必須小于等于分區(qū)數(shù),否則會(huì)導(dǎo)致線程空閑,文章還總結(jié)了創(chuàng)建Kafka分區(qū)的命令,并鼓勵(lì)讀者分享經(jīng)驗(yàn)
    2024-12-12
  • 基于dubbo分組group的一些總結(jié)

    基于dubbo分組group的一些總結(jié)

    這篇文章主要介紹了關(guān)于dubbo分組group的一些總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java打包成jar并執(zhí)行jar包中指定的main方法

    java打包成jar并執(zhí)行jar包中指定的main方法

    這篇文章主要介紹了如何將java打包成可執(zhí)行的jar,并執(zhí)行jar包中指定的main方法的相關(guān)資料,文中給出了詳細(xì)的示例代碼,對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-03-03
  • SpringBoot大學(xué)心理服務(wù)系統(tǒng)實(shí)現(xiàn)流程分步講解

    SpringBoot大學(xué)心理服務(wù)系統(tǒng)實(shí)現(xiàn)流程分步講解

    本系統(tǒng)主要論述了如何使用JAVA語(yǔ)言開(kāi)發(fā)一個(gè)大學(xué)生心理服務(wù)系統(tǒng) ,本系統(tǒng)將嚴(yán)格按照軟件開(kāi)發(fā)流程進(jìn)行各個(gè)階段的工作,采用B/S架構(gòu),面向?qū)ο缶幊趟枷脒M(jìn)行項(xiàng)目開(kāi)發(fā)
    2022-09-09
  • OpenJDK源碼解析之System.out.println詳解

    OpenJDK源碼解析之System.out.println詳解

    這篇文章主要介紹了OpenJDK源碼解析之System.out.println詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04

最新評(píng)論

保康县| 中宁县| 望江县| 麦盖提县| 曲麻莱县| 崇左市| 辽宁省| 西贡区| 酒泉市| 永川市| 渝中区| 和平县| 南康市| 长沙市| 黔东| 隆尧县| 高阳县| 钟山县| 广河县| 大关县| 洛扎县| 家居| 类乌齐县| 长宁区| 怀来县| 迁安市| 大洼县| 谢通门县| 满城县| 嘉兴市| 周至县| 昌平区| 花垣县| 翁牛特旗| 柯坪县| 嘉黎县| 新巴尔虎右旗| 乐业县| 临夏县| 清水县| 井研县|