返回顶部
首页 > 资讯 > 后端开发 > Python >Java并发编程ReentrantReadWriteLock加读锁流程
  • 293
分享到

Java并发编程ReentrantReadWriteLock加读锁流程

Java并发ReentrantReadWriteLockJava并发加读锁 2023-05-19 17:05:01 293人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录正文属性介绍加锁成功处理正文 protected final int tryAcquireShared(int unused) { Thread current = Th

正文

protected final int tryAcquireShared(int unused) {
    Thread current = Thread.currentThread();
    int c = getState();
    if (exclusiveCount(c) != 0 &&
        getExclusiveOwnerThread() != current)
        return -1;
    int r = sharedCount(c);
    if (!readerShouldBlock() &&
        r < MAX_COUNT &&
        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 1;
    }
    return fullTryAcquireShared(current);
}

上面是尝试加读锁流程的代码,既然这篇是番外篇,那就不按正常流程一点一点去分析了,着重拿出一部分来分析一下。ReentrantReadWriteLockReentrantLock相比,除了多了读写锁之外,还增加了很多属性,比如firstReaderfirstReaderHoldCountcachedHoldCounter......那我们这篇文章就介绍一下这些新属性的含义以及上面代码中加锁成功后的处理。

属性介绍

static final class HoldCounter {
    int count = 0;
    final long tid = getThreadId(Thread.currentThread());
}

HoldCount类型用来存储线程ID和线程持有的读锁数量

private transient ThreadLocalHoldCounter readHolds;
static final class ThreadLocalHoldCounter
    extends ThreadLocal&lt;HoldCounter&gt; {
    public HoldCounter initialValue() {
        return new HoldCounter();
    }
}

readHolds通过ThreadLocal在线程本地存储了一个HoldCounter对象,表示当前线程持有的读锁重入数量,主要是为了方便在发生重入或者释放锁时,分别计算每个线程持有的读锁数量。

private transient HoldCounter cachedHoldCounter;

cachedHoldCounter存储的是最后一个获取读锁成功的线程持有的读锁数量。但是如果只有一个线程获取读锁,会使用firstReaderfirstReaderHoldCount来记录线程持有读锁数量,只有获取读锁的线程数大于1时才会用cachedHoldCounter存储最后线程持有的读锁数量。

private transient Thread firstReader = null;

第一个获取读锁的线程,确切地说是把读锁数量从0改成1的线程,并且当前还没有释放锁。如果第一个线程释放了锁,就会把firstReader设为null,只有当所有读锁释放之后,下一个获取读锁成功的线程就成为firstReader

private transient int firstReaderHoldCount;

第一个获取读锁的线程持有读锁的数量。

加锁成功处理

int r = sharedCount(c);
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++;
}

这里截取加锁成功之后处理的代码来分析下对这些属性的操作。

  • if (r == 0)表示共享锁数量为0,当前线程就是第一个获取读锁成功的线程,所以firstReaderfirstReaderHoldCount记录的就是当前线程。
  • 如果读锁数量不是0,但是当前线程是第一个线程,那就直接在原来数量基础上进行累加 firstReaderHoldCount++;
  • 如果读锁数量不为0,而且当前线程也不是第一个线程,这时就需要用到cachedHoldCounter了。
    • rh == null表示当前线程是第二个线程,rh.tid != getThreadId(current)表示当前线程至少是第三个线程(这里不考虑重入情况,只考虑当前线程第一次获取读锁成功),两个条件合起来可以理解为之前缓存的最后一个获取读锁成功的线程不是当前线程,所以就需要更新为当前线程cachedHoldCounter = rh = readHolds.get()
    • 如果之前缓存的最后一个线程是当前线程,那么就会有一个特殊情况rh.count == 0,这里可以理解为一个线程释放了读锁之后又重新获取了读锁,释放完所有锁时,为了防止内存泄漏会调用readHolds.remove()清除线程本地存储的信息,而现在加锁成功了就需要在线程本地重新记录持有锁的数量,既然缓存的就是当前线程的,那就直接用缓存来更新到线程本地就可以了。

以上就是Java并发编程ReentrantReadWriteLock番外的详细内容,更多关于java并发ReentrantReadWriteLock的资料请关注编程网其它相关文章!

--结束END--

本文标题: Java并发编程ReentrantReadWriteLock加读锁流程

本文链接: https://lsjlt.com/news/213529.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java并发编程ReentrantReadWriteLock加读锁流程
    目录正文属性介绍加锁成功处理正文 protected final int tryAcquireShared(int unused) { Thread current = Th...
    99+
    2023-05-19
    Java并发ReentrantReadWriteLock Java并发加读锁
  • Java多线程读写锁ReentrantReadWriteLock类详解
    目录ReentrantReadWriteLock读读共享写写互斥读写互斥源码分析写锁的获取与释放读锁的获取与释放参考文献真实的多线程业务开发中,最常用到的逻辑就是数据的读写,Reen...
    99+
    2024-04-02
  • Java 多线程并发 ReentrantReadWriteLock详情
    目录前言ReadWriteLockReentrantReadWriteLock 源码分析类关系SyncHoldCounterThreadLocalHoldCounter属性构造方法核...
    99+
    2024-04-02
  • java并发编程中ReentrantLock可重入读写锁
    目录一、ReentrantLock可重入锁二、ReentrantReadWriteLock读写锁三、读锁之间不互斥一、ReentrantLock可重入锁 可重入锁ReentrantL...
    99+
    2024-04-02
  • 如何解析Java多线程读写锁ReentrantReadWriteLock类
    这篇文章将为大家详细讲解有关如何解析Java多线程读写锁ReentrantReadWriteLock类,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。真实的多线程业务开发中,最常用到的逻辑就是...
    99+
    2023-06-22
  • java并发编程StampedLock高性能读写锁详解
    目录一、读写锁二、悲观读锁三、乐观读一、读写锁 在我的《java并发编程》上一篇文章中为大家介绍了《ReentrantLock读写锁》,ReentrantReadWriteLock可...
    99+
    2024-04-02
  • Java多线程并发ReentrantReadWriteLock源码分析
    本篇内容主要讲解“Java多线程并发ReentrantReadWriteLock源码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java多线程并发ReentrantReadWriteLoc...
    99+
    2023-07-02
  • Java并发编程之StampedLock锁介绍
    StampedLock: StampedLock是并发包里面JDK8版本新增的一个锁,该锁提供了三种模式的读写控制,当调用获取锁的系列函数时,会返回一个long 型的变量,我们称之为...
    99+
    2024-04-02
  • Java并发编程中死锁的实现
    这篇文章给大家介绍Java并发编程中死锁的实现,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、什么是死锁所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进二、死锁产生的...
    99+
    2023-06-15
  • 一文读懂 Java Memory Model:解锁并发编程中的疑惑
    Java Memory Model, JMM, 并发编程, 内存一致性, 可见性, 有序性 Java Memory Model(JMM)是理解并发编程中内存一致性的关键。它定义了多线程程序中共享变量的可见性、有序性等规则,帮助开发者理解和...
    99+
    2024-02-04
  • Go语言并发编程之互斥锁Mutex和读写锁RWMutex
    目录一、互斥锁Mutex1、Mutex介绍2、Mutex使用实例二、读写锁RWMutex1、RWMutex介绍2、RWMutex使用实例在并发编程中,多个Goroutine访问同一块...
    99+
    2024-04-02
  • Java并发编程之StampedLock锁怎么应用
    本篇内容介绍了“Java并发编程之StampedLock锁怎么应用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!StampedLock:St...
    99+
    2023-06-30
  • Java并发编程的悲观锁和乐观锁机制
    本篇内容主要讲解“Java并发编程的悲观锁和乐观锁机制”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java并发编程的悲观锁和乐观锁机制”吧!一、资源和加锁1、场景描述多线程并发访问同一个资源问...
    99+
    2023-06-16
  • 并发编程中如何使用Java中的锁?
    并发编程中如何使用Java中的锁? 在Java中,锁是一种用来控制多个线程访问共享资源的机制。锁可以保证在同一时刻只有一个线程可以访问共享资源,从而避免多个线程同时修改数据导致的数据不一致问题。Java中的锁可以分为两种类型:内置锁和显式锁...
    99+
    2023-08-28
    numy shell 并发
  • Java并发编程之显式锁机制详解
            我们之前介绍过synchronized关键字实现程序的原子性操作,它的内部也是一种加锁和解锁机制,是一种声明式的编程方式,我们只需要对方法或者代码块进行声...
    99+
    2023-05-30
    java 并发编程 显式锁机制
  • 详解JUC并发编程之锁
    目录1、自旋锁和自适应锁2、轻量级锁和重量级锁轻量级锁加锁过程轻量级锁解锁过程3、偏向锁4、可重入锁和不可重入锁5、悲观锁和乐观锁6、公平锁和非公平锁7、共享锁和独占锁8、可中断锁和...
    99+
    2024-04-02
  • java线程安全锁ReentrantReadWriteLock原理分析readLock
    目录前言ReentrantReadWriteLock的简单使用readLock源码分析lock()acquireShared()tryAcquireShared()fullTryAc...
    99+
    2024-04-02
  • java并发编程死锁定义及如何避免死锁
    目录场景模拟分析场景一:狭路相逢场景二:冷战场景三:哲学家就餐场景四:竞争资源死锁是什么?产生死锁的的四个条件如下:如何避免死锁?方案一:破坏不剥夺条件方案二:破坏请求与保持条件方案...
    99+
    2024-04-02
  • Java并发编程中的悲观锁和乐观锁机制
    这篇文章主要介绍“Java并发编程中的悲观锁和乐观锁机制”,在日常操作中,相信很多人在Java并发编程中的悲观锁和乐观锁机制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java并发编程中的悲观锁和乐观锁机制...
    99+
    2023-06-02
  • Java并发编程加锁导致的活跃性问题详解方案
    目录死锁(Deadlock)死锁的解决和预防1.超时释放锁2.按顺序加锁3.死锁检测活锁(Livelock)避免活锁饥饿解决饥饿性能问题上下文切换什么是上下文切换?减少上下文切换的方...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作