源码分析--ReentrantReadWriteLock(一)

ReentrantReadWriteLock之深入源码解析 ReentrantLock是排他锁,在高并发读多写少的场景下,同时还要保证线程安全,如果使用ReentrantLock的效率不是那么好,所以才有了ReentrantReadWriteLock。在讲源码之前,我们对读写锁要有个认知。读读操作是共享的。读写操作是互斥的。写写操作是互斥的。写读操作是互斥的。(写读两个不同线程)单线程获取写锁后,再次获取读锁,可以拿到。(写读操作可以重入)单线程获取读锁后,再次获取写锁,不可以拿到。 阅读详情

概述

ReentrantReadWriteLock 是读写锁,它维护了一对锁:一个读锁,一个写锁。读锁之间是共享的,写锁是互斥的。与 ReentrantLock 相比,读写锁在读多写少的场景下允许更高的并发量。

类图如下:

在这里插入图片描述
ReentrantReadWriteLock中的类分成三个部分:
(1)ReentrantReadWriteLock本身实现了ReadWriteLock接口,这个接口只提供了两个方法readLock()和writeLock();
(2)同步器,包含一个继承了AQS的Sync内部类,以及其两个子类FairSync和NonfairSync;
(3)ReadLock和WriteLock两个内部类实现了Lock接口,它们具有锁的一些特性。

源码分析

构造方法:

// 默认构造方法
public ReentrantReadWriteLock() {
    this(false);
}
// 是否使用公平锁的构造方法
public ReentrantReadWriteLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
    readerLock = new ReadLock(this);
    writerLock = new WriteLock(this);
}

与 ReentrantLock 类似,这里的构造器也传入了公平策略,且默认为非公平。构造器内部初始化了三个变量:sync、readerLock 和 writerLock,如下:

// 提供读锁的内部类
private final ReentrantReadWriteLock.ReadLock readerLock;

// 提供写锁的内部类
private final ReentrantReadWriteLock.WriteLock writerLock;

// 执行所有的同步机制
final Sync sync;

内部类Sync:
Sync 类继承自 AQS(与 ReentrantLock 中的 Sync 类似),如下:

abstract static class Sync extends AbstractQueuedSynchronizer {
    // 使用 AQS 中的 state 变量(int 类型)来记录读写锁的占用情况
    // 其中高 16 位记录读锁的持有次数;低 16 位记录写锁的重入次数
    static final int SHARED_SHIFT   = 16;
    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
    static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

    // 共享锁(读锁)的持有次数
    static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
    // 互斥锁(写锁)的重入次数
    static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

    /**
     * 每个线程持有读锁的计数器。
     * 以 ThreadLocal 形式保存,缓存在 cachedHoldCounter
     * 该类的主要作用是记录线程持有读锁的数量,可理解为 <tid,count> 的形式
     */    
    static final class HoldCounter {
        int count = 0;
        // Use id, not reference, to avoid garbage retention
        final long tid = getThreadId(Thread.currentThread());
    }

    static final class ThreadLocalHoldCounter
        extends ThreadLocal<HoldCounter> {
        public HoldCounter initialValue() {
            return new HoldCounter();
        }
    }

    /**
     * 当前线程持有的可重入读锁的数量(数量为0时删除)。
     */
    private transient ThreadLocalHoldCounter readHolds;

    private transient HoldCounter cachedHoldCounter;

    /**
     * firstReader:第一个获取读锁的线程;
     * firstReaderHoldCount:firstReader 的持有计数。
     */
    private transient Thread firstReader = null;
    private transient int firstReaderHoldCount;

    Sync() {
        readHolds = new ThreadLocalHoldCounter();
        setState(getState()); // ensures visibility of readHolds
    }

    /*
     * 对于公平锁和非公平锁,获取和释放锁使用的代码相同;
     * 但在队列非空时,它们是否或如何允许插入的方式不同。
     */

    /**
     * 当前线程在尝试(或有资格)获取读锁时,是否应该由于策略原因而阻塞。
     */
    abstract boolean readerShouldBlock();

    /**
     * 当前线程在尝试(或有资格)获取写锁时,是否应该由于策略原因而阻塞。
     */
    abstract boolean writerShouldBlock();

    // 释放写锁
    protected final boolean tryRelease(int releases) {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        int nextc = getState() - releases;
        boolean free = exclusiveCount(nextc) == 0;
        if (free)
            setExclusiveOwnerThread(null);
        setState(nextc);
        return free;
    }

    // 获取写锁
    protected final boolean tryAcquire(int acquires) {
        /*
         * 流程:
         * 1. 若其他线程持有读锁或写锁(计数不为零),返回 false;
         * 2. 若持有数量饱和(超出上限),返回 false;
         * 3. 该线程有资格获取锁,更新 state 并设置为 owner。
         */
        Thread current = Thread.currentThread();
        int c = getState();
        int w = exclusiveCount(c);
        if (c != 0) {
            // (Note: if c != 0 and w == 0 then shared count != 0)
            if (w == 0 || current != getExclusiveOwnerThread())
                return false;
            if (w + exclusiveCount(acquires) > MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            // Reentrant acquire
            setState(c + acquires);
            return true;
        }
        // 若获取写锁时应该阻塞,或者更新 state 失败,返回 false
        if (writerShouldBlock() ||
            !compareAndSetState(c, c + acquires))
            return false;
        setExclusiveOwnerThread(current);
        return true;
    }

    // 释放读锁
    protected final boolean tryReleaseShared(int unused) {
        Thread current = Thread.currentThread();
        // 若当前线程是第一个持有读锁的线程
        if (firstReader == current) {
            // assert firstReaderHoldCount > 0;
            if (firstReaderHoldCount == 1)
                firstReader = null;
            else
                firstReaderHoldCount--;
        } else {
            // 更新缓存
            HoldCounter rh = cachedHoldCounter;
            if (rh == null || rh.tid != getThreadId(current))
                rh = readHolds.get();
            int count = rh.count;
            if (count <= 1) {
                readHolds.remove();
                if (count <= 0)
                    throw unmatchedUnlockException();
            }
            --rh.count;
        }
        // 更新 state
        for (;;) {
            int c = getState();
            int nextc = c - SHARED_UNIT;
            if (compareAndSetState(c, nextc))
                // Releasing the read lock has no effect on readers,
                // but it may allow waiting writers to proceed if
                // both read and write locks are now free.
                return nextc == 0;
        }
    }

    // 获取读锁
    protected final int tryAcquireShared(int unused) {
        /*
         * 流程:
         * 1. 如果其他线程持有写锁,获取失败;
         * 2. 否则,该线程有资格获取,因此请询问它是否由于队列策略而阻塞;
         *    若不阻塞,尝试通过 CAS 更新状态计数。
         *    注意:这一步没有检查可重入的获取,推迟到完整版本,
         *         以避免在明显不可重入的情况下检查持有计数。
         * 3. 如果第二步失败,要么是因为线程明显不符合条件、CAS 失败或计数饱和,
         *    则进行完整重试版本。
         */
        Thread current = Thread.currentThread();
        int c = getState();
        // step1. 若写锁被其他线程占用,则获取失败
        //        exclusiveCount(c) != 0表示写锁被占用
        if (exclusiveCount(c) != 0 &&
            getExclusiveOwnerThread() != current)
            return -1;
        // step2. 获取读锁数量
        int r = sharedCount(c);
        if (!readerShouldBlock() &&
            r < MAX_COUNT &&
            compareAndSetState(c, c + SHARED_UNIT)) {
            // 读锁未被占用,设置该线程是第一个持有读锁的线程
            if (r == 0) {
                firstReader = current;
                firstReaderHoldCount = 1;
            // 该线程已持有读锁,计数加1
            } else if (firstReader == current) {
                firstReaderHoldCount++;
            // 其他线程已持有读锁
            } else {
                // 取缓存
                HoldCounter rh = cachedHoldCounter;
                // 若未初始化,或者拿到的不是当前线程的计数,则从 ThreadLocal 中获取
                if (rh == null || rh.tid != getThreadId(current))
                    cachedHoldCounter = rh = readHolds.get();
                else if (rh.count == 0)
                    readHolds.set(rh);
                // 增加计数
                rh.count++;
            }
            // 获取成功
            return 1;
        }
        // step3. 若step2获取失败,则执行该步骤
        return fullTryAcquireShared(current);
    }

    /**
     * 获取读锁的完整版,处理 tryAcquireShared 中未处理的 CAS 丢失和可重入读取。
     */
    final int fullTryAcquireShared(Thread current) {
        HoldCounter rh = null;
        for (;;) {
            int c = getState();
            // 如果其他线程占用写锁,获取失败
            if (exclusiveCount(c) != 0) {
                if (getExclusiveOwnerThread() != current)
                    return -1;
                // else we hold the exclusive lock; blocking here
                // would cause deadlock.
            } else if (readerShouldBlock()) {
                // Make sure we're not acquiring read lock reentrantly
                if (firstReader == current) {
                    // assert firstReaderHoldCount > 0;
                } else {
                    if (rh == null) {
                        rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current)) {
                            rh = readHolds.get();
                            if (rh.count == 0)
                                readHolds.remove();
                        }
                    }
                    if (rh.count == 0)
                        return -1;
                }
            }
            if (sharedCount(c) == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            if (compareAndSetState(c, c + SHARED_UNIT)) {
                if (sharedCount(c) == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;
                } else {
                    if (rh == null)
                        rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                    cachedHoldCounter = rh; // cache for release
                }
                return 1;
            }
        }
    }

    /**
     * 执行写锁的 tryLock 方法
     * 与 tryAcquire 相比,该方法未调用 writerShouldBlock
     */
    final boolean tryWriteLock() {
        Thread current = Thread.currentThread();
        int c = getState();
        if (c != 0) {
            int w = exclusiveCount(c);
            if (w == 0 || current != getExclusiveOwnerThread())
                return false;
            if (w == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
        }
        if (!compareAndSetState(c, c + 1))
            return false;
        setExclusiveOwnerThread(current);
        return true;
    }

    /**
     * 执行读锁的 tryLock 方法
     * 与 tryAcquireShared 相比,该方法未调用 readerShouldBlock
     */
    final boolean tryReadLock() {
        Thread current = Thread.currentThread();
        for (;;) {
            int c = getState();
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return false;
            int r = sharedCount(c);
            if (r == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            if (compareAndSetState(c, c + SHARED_UNIT)) {
                if (r == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;
                } else {
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return true;
            }
        }
    }
}

在这里插入图片描述
内部类NonfairSync :
NonfairSync 继承自 Sync 类,提供非公平策略的实现,如下:

static final class NonfairSync extends Sync {
    final boolean writerShouldBlock() {
        return false; // writers can always barge
    }
    final boolean readerShouldBlock() {
        // 调用父类 AQS 中的方法实现
        return apparentlyFirstQueuedIsExclusive();
    }
}

// 若头节点的下一个节点是写线程,为了防止写线程饥饿等待,当前的读线程应该阻塞
final boolean apparentlyFirstQueuedIsExclusive() {
    Node h, s;
    return (h = head) != null &&
        (s = h.next)  != null &&
        !s.isShared()         &&
        s.thread != null;
}

非公平策略中,writerShouldBlock 返回 false,说明写线程无需阻塞;

readerShouldBlock 则是调用父类 AQS 中的 apparentlyFirstQueuedIsExclusive 方法实现的,该方法通过判断等待队列中的第一个线程是否为写线程,若是则返回 true,表示给写线程让道。

内部类FairSync:

static final class FairSync extends Sync {
    final boolean writerShouldBlock() {
        return hasQueuedPredecessors();
    }
    final boolean readerShouldBlock() {
        return hasQueuedPredecessors();
    }
}

在公平策略中,两个方法都通过调用父类 AQS 的 hasQueuedPredecessors 方法判别,二者都是根据等待队列中是否有其他线程,若有其他线程,则当前线程等待。
这就是公平的体现吧:无论读写,都乖乖去排队,别插队。

其他内容后续学习补充~

ReentrantReadWriteLock源码分析 本文深入分析了ReentrantReadWriteLock的实现原理,主要特点包括:1. 通过一对关联的读锁(共享)和写锁(独占)实现;2. 支持锁降级(写锁降为读锁);3. 读读共享、读写互斥、写写互斥的锁策略;4. 可重入特性。源码层面详细剖析了读锁的获取(tryAcquireShared)和释放(tryReleaseShared)流程,包括CAS更新状态、等待队列处理等核心机制。写锁实现与ReentrantLock类似,通过exclusiveCount维护独占性。整体基于AQS框架,在低竞争场景下性能 阅读详情

相关推荐

深入CARLA地图底层:OpenDRIVE文件如何影响你的仿真效果与避坑指南

本文深入解析CARLA仿真中OpenDRIVE地图文件的核心作用,揭示其如何影响车道连接、交通规则和导航逻辑。通过实战案例和代码示例,提供五大典型地图问题的诊断与修复方案,帮助开发者优化仿真效果并规避常见陷阱。

weixin_34180452的博客 276

AQS源码解读(七)——ReentrantReadWriteLock原理详解(读写锁是一把锁吗?如何一把锁两个状态?)

ReentrantReadWriteLock作为读写锁,整体架构和实现都与ReentrantLock类似,不同之处在于ReentrantReadWriteLock分为读锁和写锁,读锁是共享锁,可多个读线程共享一把锁;写锁是互斥锁,只能有一个线程持有锁。同样ReentrantReadWriteLock也是基于AQS实现的。

你学废了吗? 1113

手机也能跑!5.6MB的AnimeGANv3模型部署实战:从PyTorch到ONNX再到移动端推理

本文详细介绍了如何将轻量级动画生成器AnimeGANv3从PyTorch模型转换为ONNX格式,并部署到移动端进行实时推理。通过5.6MB的极简模型设计和优化策略,实现在手机等边缘设备上的高效动漫风格转换,涵盖模型准备、格式转换、移动端优化及性能调优全流程。

weixin_33724059的博客 383

并发编程笔记四-ReentrantReadWriteLock源码深度解析

通过前面的学习,我们知道ReentrantLock已经实现了互斥锁的功能,并且ReentrantLock已经有了非常丰富的API可使用,完全可以保障我们并发编程时对于线程安全的高要求。既然如此,为什么又出现了一个ReentrantReadWriteLock呢?原来啊,在一个读多写少的场景下,如果我们采用synchronized或者说ReentrantLock,其效率是非常低的,就像前面说的,它们都是互斥锁。在这种情况下,咱们就可以使用ReentrantReadWriteLock读写锁去实现。

qq_41191331的博客 1084

从零配置到批量处理:FaceFusion 3.1完整使用指南(含hififace_256模型测试)

本文详细介绍了FaceFusion 3.1的完整使用指南,包括环境配置、模型选择(特别是hififace_256模型的深度测试)以及批量处理技巧。通过AI驱动的脸部替换技术,帮助用户高效实现高质量的面部处理,适用于影视制作、广告设计等多种场景。

weixin_29056865的博客 655

金属粘结剂喷射3D打印技术:工艺流程与后处理关键

金属粘结剂喷射(Binder Jetting)是一种创新的增材制造技术,通过逐层喷射粘合剂将金属粉末粘结成型,再经过脱脂和烧结等后处理工序获得最终零件。这项技术的核心优势在于无需支撑结构、可实现批量生产,并且材料利用率高。在3D打印领域,金属BJ技术特别适合中小尺寸、结构复杂且表面质量要求高的零件生产。其工艺流程包括前期数据处理、打印生胚阶段、拆包与清粉,以及关键的渗透、脱脂和烧结后处理环节。后处理工艺的控制直接决定了零件的机械性能和尺寸精度,其中烧结工艺尤为关键,需要精确控制温度曲线和气氛环境。金属BJ打

weixin_35751194的博客 83

【并发编程】史上最详细的ReentrantReadWriteLock源码刨析

史上最详细的ReentrantReadWriteLock源码刨析,带你深入代码底层原理,彻底搞懂ReentrantReadWriteLock。

小七的博客 582

告别手动改图!用Python+PyWin32驱动SolidWorks,实现参数自动化修改(保姆级避坑指南)

本文详细介绍了如何利用Python和PyWin32驱动SolidWorks实现参数自动化修改,提供从环境配置到API连接的工业级解决方案。通过实战案例和避坑指南,帮助工程师高效搭建自动化脚本工作流,显著提升设计效率。

weixin_30614109的博客 741

ReentrantReadWriteLock 源码debug详解

ReentrantReadWriteLock 源码debug详解

weixin_46569562的博客 1422

别再傻傻分不清PBR和NPR了!从《原神》到《双城之战》,聊聊游戏里那些让你眼前一亮的渲染风格

本文深入解析了PBR(基于物理的渲染)与NPR(非真实感渲染)在游戏视觉风格中的应用差异,通过《原神》和《双城之战》的案例,展示了两种渲染技术如何创造出截然不同的艺术效果。从技术原理到实战案例,帮助读者理解如何根据项目需求选择合适的渲染风格。

weixin_30425949的博客 146

LeRobot 入门教程(七)数据集

LeRobot Dataset v3.0 是机器人学习数据的标准化格式,支持多模态时间序列数据和视频的统一访问。该版本通过基于文件的存储(Parquet/MP4)、关联元数据和Hub原生流式处理等新特性,显著提升了性能并降低了存储开销。文档详细介绍了格式设计、安装使用、数据记录与加载方法,以及从v2.1迁移到v3.0的步骤,特别针对大型数据集(如DROID 1.0.1)的处理提供了SLURM集群移植方案。v3.0通过优化文件组织和元数据管理,实现了更快的加载速度、更高的内存效率和更好的可扩展性。

2506_90492529的博客 2052

ReentrantReadWriteLock源码分析(一)

此处源码分析,主要是基于读锁,非公平机制,JDK1.8。 问题: 1、ReentrantReadWriteLock是如何创建读锁与写锁? 2、读锁与写锁的区别是什么? 3、锁的重入次数与获取锁的线程数分别是用哪种方式记录的? 4、当队列中出现多个共享模式的线程节点连续排列时,那么当第一个共享模式的线程拿到锁之后,后面的共享线程节点怎么获取锁? 一、创建ReadLock。 Reen...

weixin_30532837的博客 66

BES2700的PMU

BES2700ZP-BES2700芯片的PMU架构分析摘要:本文档分析了BES2700芯片的电源管理单元(PMU)架构。实际应用中仅需为VBAT引脚供电,其余电源均由芯片内部PMU提供。文档包含架构示意图、问题列表和参考链接,涉及PMU工作原理、外部供电要求等关键技术点。待解决问题包括具体供电参数和内部电源转换机制等。通过添加日志信息和代码片段,为开发人员提供了调试PMU功能的实用方法。

云淡风轻 117

多线程7一ReentrantReadWriteLock源码分析

ReentrantReadWriteLock分别实现读锁和写锁,在大多数并发场景下读多于写,是比ReentrantLock 排他锁的并发性能好,吞吐量高,合理运用,可以使我们程序运行更有效率!

随珠和璧 217

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

java高并发类lock,Java高并发系列之ReentrantReadWriteLock源码分析(一)

实际上,在多线程并发环境下,读数据不会对数据造成修改,因此不需要加锁就可以。在ReentrantReadWriteLock类中,将读操作和写操作拆分为两把锁,分别是读锁:ReadLock和写锁:WriteLock。这种读写分离的操作,运行多线程同时读取数据,在写操作的时候,才是独占的。我们先来看看ReentrantReadWriteLock的类图,了解其结构。这样我们看源码也能一目了然,印象也会深...

weixin_42309785的博客 111

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

大厂之路一由浅入深、并行基础、源码分析一 “J.U.C.L”之读写锁ReentrantReadWriteLock源码级分析(基于AQS、共享/独占锁)

文章部分总结于:点击!!!!!! 文章部分总结于:点击!!!!!! AQS 定义了两种资源共享方式读写锁ReentrantReadWriteLock读写锁ReentrantReadWriteLock的结构读写锁ReentrantReadWriteLock的方法读写锁ReentrantReadWriteLock的使用 AQS 定义了两种资源共享方式 Exclusive: 独占,只有一个线程能执行,如ReentrantLock 对于独占锁的主要源码,已经通过重入锁的文章进了深入的分析,所以不再过多阐述.

置身于量子事业的软件开发爱好者 551

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

关于ReentrantReadWriteLock,首个获取读锁的线程单独记录问题讨论(该如何更好的阅读源码)

`firstReader`表示第一个获取读锁的线程,若当前线程等于`firstReader`,读锁重入时`firstReaderHoldCount+1`,而非首个获取读锁的线程则用一个继承了`ThreadLocal`的内部类`ThreadLocalHoldCounter`给每个线程计数。为什么第一个线程不用`ThreadLocalHoldCounter`计数呢?单独拎出来的意义何在?

你学废了吗? 893

【锁】读写锁--ReentrantReadWriteLock源码分析

1.什么读写锁–ReentrantReadWriteLock? 撸源码前,可先看:【锁】公平锁/非公平锁/可重入锁/递归锁/自旋锁/独占锁/共享锁/读写锁 2.开撸 2.1 类图 先从类图开始,一步一步看。 idea找到依赖的jdk下面rt.jar里面JUC包里面的ReentrantReadWriteLock右键如图: 打开类图: 我们可以看到ReentrantLock里面有一个Sync抽象...

aaa_bbb_ccc_123_456的博客 2458

ReentrantReadWriteLock读写锁源码分析

ReentrantReadWriteLock读写锁源码分析 读写状态的设计 ReentrantReadWriteLock也是通过自定义AQS(抽象队列同步器)实现。同步器内部只有一个状态,而读写锁需要维护两个状态:读状态与写状态。 ReentrantReadWriteLock将同步器内部的状态state按位进行拆分:高16位代表读状态,低16位代表写状态。 java.util.concurrent.locks.ReentrantReadWriteLock.Sync static final int SHAR

morris 2万+

【并发编程学习篇】ReentrantReadWriteLock详解

现实中有这样一种场景对共享资源有读和写的操作,且写操作没有读操作那么频繁(读多写少)在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源(读读可以并发)但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写操作了(读写,写读,写写互斥)在读多于写的情况下,读写锁能够提供比排它锁更好的并发性和吞吐量。

一个勤勤恳恳的程序猿 3万+

7、ReentrantReadWriteLock源码分析

简介: ReentrantReadWriteLock是解决计算机场景的读写场景,并发场景有读线程和写线程同时对一个资源操作,且读场景远远多于写场景,多个读线程共享一个资源没有问题,但是多个写线程不能同时共享一个资源。 前提: ReentrantReadWriteLock进入读锁前提:无其他写锁 ReentrantReadWriteLock进入写锁前提:无其他写锁 且 无其他读锁 特性: 功能 可重入锁 不可重入锁 公平锁 非公平锁 独占锁 可中断锁 锁降级

爱欧米 451

源码分析J.U.C之ReentrantReadWriteLock底层原理

ReentrantReadWriteLock看这一篇就够了~~~

zqy_zq_zxl的博客 3338

JDK源码分析-ReentrantReadWriteLock

概述 前面分析过 ReentrantLock「JDK源码分析-ReentrantLock」,它是一种互斥的可重入锁,可用于处理并发场景下的线程安全问题。而很多时候会出现“读多写少”的情况,若用 ReentrantLock 会降低并发量,此时就比较适合 ReentrantReadWriteLock 出场了。 ReentrantReadWriteLock 是读写锁,它维护了一对锁:一...

WriteOnRead 2005
上一篇: 源码分析--Semaphore
下一篇: 源码分析--Lock&ReentrantLock
CodersCoder
博客等级 码龄10年 90粉丝 258原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值