0

0

JAVA之ReadWriteLock接口及其实现ReentrantReadWriteLock方法

怪我咯

怪我咯

发布时间:2017-06-30 10:32:38

|

1575人浏览过

|

来源于php中文网

原创

下面小编就为大家带来一篇readwritelock接口及其实现reentrantreadwritelock方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

Java并发包的locks包里的锁基本上已经介绍得差不多了,ReentrantLock重入锁是个关键,在清楚的了解了同步器AQS的运行机制后,实际上再分析这些锁就会显得容易得多,这章节主讲另外一个重要的锁——ReentrantReadWriteLock读写锁。

ReentrantLock是一个独占锁,也就是说只能由一个线程获取锁,但如果场景是线程只做读的操作呢?这样ReentrantLock就不是很合适,读的线程并不需要保证其线程的安全性,任何一个线程都能去获取锁,只有这样才能尽可能地保证性能和效率。ReentrantReadWriteLock就是这样的一个锁,在其内部分为读锁和写锁,可以有N个读操作线程获取到写锁,但是只能有1个写操作线程获取到写锁,那么可以预见的是写锁是共享锁(AQS中的共享模式),读锁是独占锁(AQS中的独占模式)。首先来看读写锁的接口类:

public interface ReadWriteLock { 
  Lock readLock();  //获取读锁
  Lock writeLock();  //获取写锁
 }

可以看到ReadWriteLock接口只定义了两个方法,获取读锁和获取写锁的方法。下面是ReadWriteLock的实现类——ReentrantReadWriteLock。  

和ReentrantLock类似,ReentrantReadWriteLock在其内部也是通过一个内部类Sync实现同步器AQS,同样也是通过实现Sync实现公平锁和非公平锁,这一点的思路和ReentrantLock类似。在ReadWriteLock接口中获取的读锁和写锁是怎么实现的呢?

立即学习Java免费学习笔记(深入)”;

//ReentrantReadWriteLock
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync;
public ReentrantReadWriteLock(){
 this(false); //默认非公平锁
}
public ReentrantReadWriteLock(boolean fair) {
 sync = fair ? new FairSync() : new NonfairSync(); //锁类型(公平/非公平)
 readerLock = new ReadLock(this); //构造读锁
 writerLock = new WriteLock(this); //构造写锁
}
……
public ReentrantReadWriteLock.WriteLock writeLock0{return writerLock;}
public ReentrantReadWriteLock.ReadLock readLock0{return ReaderLock;}
//ReentrantReadWriteLock$ReadLock
public static class ReadLock implements Lock {
 protected ReadLock(ReentrantReadwritLock lock) {
  sync = lock.sync;  //最后还是通过Sync内部类实现锁
  }
 …… //它实现的是Lock接口,其余的实现可以和ReentrantLock作对比,获取锁、释放锁等等
}
//ReentrantReadWriteLock$WriteLock
public static class WriteLock implemnts Lock {
 protected WriteLock(ReentrantReadWriteLock lock) {
  sync = lock.sync;
  }
…… //它实现的是Lock接口,其余的实现可以和ReentrantLock作对比,获取锁、释放锁等等
}

上面是对ReentrantReadWriteLock做了一个大致的介绍,可以看到在其内部有好几个内部类,实际上读写锁内有两个锁——ReadLock、WriteLock,这两个锁都是实现自Lock接口,可以和ReentrantLock对比,而这两个锁的内部实现则是通过Sync,也就是同步器AQS实现的,这也可以和ReentrantLock中的Sync对比。
  回顾一下AQS,其内部有两个重要的数据结构——一个是同步队列、一个则是同步状态,这个同步状态应用到读写锁中也就是读写状态,但AQS中只有一个state整型来表示同步状态,读写锁中则有读、写两个同步状态需要记录。所以,读写锁将AQS中的state整型做了一下处理,它是一个int型变量一共4个字节32位,那么可以读写状态就可以各占16位——高16位表示读,低16位表示写。

  

现在有一个疑问如果state的值位5,二进制为(00000000000000000000000000000101),如何快速确定读和写各自的状态呢?这就要用到位移运算了。计算方式为:写状态state & 0x0000FFFF,读状态state >>> 16。写状态增加1等于state + 1,读状态增加1等于state + (1 位运算可以参考《>、>>>移位操作》。

写锁的获取与释放

基于USB和LabVIEW的虚拟仪器的设计 word版
基于USB和LabVIEW的虚拟仪器的设计 word版

虚拟仪器和USB的接口技术在 仪器研发领域受到了密切关注.数据采集及控制的智能外设采用USB接口改善了其瓶颈现象,也加强了它与通用计算机的“亲和力”.普通的MCS-51单片机 没有USB接口,作为虚拟仪器应用软件开发平台之一的LabVIEW也没有提供USB接口的驱动程序.为此,介绍了基于USB和LabVIEW的虚拟仪器 的设计原理以及USB开发的方法,提出一种开发简单的设计方案.阐述了利用FT245 BM进行USB开发的过程,给出FT245 BM与AVR单片机AT9

下载

根据我们之前的经验可以得知:AQS已经将获取锁的算法骨架搭好了,只需子类实现tryAcquire(独占锁),故我们只需查看tryAcquire。

//ReentrantReadWriteLock$Sync
protected final boolean tryAcquire(int acquires) {
 Thread current = Thread.currentThread;
 int c = getState(); //获取state状态
 int w = exclusiveCount(c); //获取写状态,即 state & 0x00001111
 if (c != 0) { //存在同步状态(读或写),作下一步判断
  if (w == 0 || current != getExclusiveOwnerThread())  //写状态为0,但同步状态不为0表示有读状态,此时获取锁失败,或者当前已经有其他写线程获取了锁此时也获取锁失败
   return false;
  if (w + exclusiveCount(acquire) > MAX_COUNT) //锁重入是否超过限制
   throw new Error(“Maxium lock count exceeded”);
  setState(c + acquire); //记录锁状态
  return true;
  }
  if (writerShouldBlock() || !compareAndSetState(c, c + acquires))
   return false;  //writerShouldBlock对于非公平锁总是返回false,对于公平锁则判断同步队列中是否有前驱节点
  setExclusiveOwnerThread(current);
  return true;
}

上面是写锁的状态获取,不好理解的是writerShouldBlock方法,此方法上面有描述,非公平锁直接返回false,而对于公平锁则是调用hasQueuedPredecessors方法如下:

 //ReentrantReadWriteLock$FairSync
 final boolean writerShouldBlock() {
  return hasQueuedPredecessors();
 }

原因是为什么呢?这就要回到非公平锁和公平锁的区别上来了,简单回顾一下,详情可参考《5.Lock接口及其实现ReentrantLock》。对于非公平锁,每次线程获取锁时首先会强行进行锁获取操作而不管同步队列中是否有线程,当获取不到时才会将线程构造至队尾;对于公平锁来讲,只要同步队列中存在线程,就不会去获取锁,而是将线程构造添加至队尾。所以重新回到写状态的获取上,tryAcquire方法里,前面发现没有线程持有锁,但是此时会根据锁的不同做相应操作,对于非公平锁——抢锁,对公平锁——同步队列中有线程,不抢锁,添加至队尾排队。

写锁的释放与ReentrantLock的释放过程基本类似,毕竟都是独占锁,每次释放减少写的状态,直到减小到0就表示写锁已经完全释放。

读锁的获取与释放

同理,根据我们之前的经验可以得知:AQS已经将获取锁的算法骨架搭好了,只需子类实现tryAcquireShared(共享锁),故我们只需查看tryAcquireShared。我们知道对于共享模式下的锁,它能够被多个线程同时获取,现在问题来了,T1线程获取了锁,同步状态state=1,此时T2也获取了锁,state=2,接着T1线程重入state=3,也就是说读状态是所有线程读锁次数的总和,而每个线程各自获取读锁的次数只能选择保存在ThreadLock中,由线程自身维护,所以在这个地方要做一些复杂处理,源码有点长,但复杂就在于每个线程保存自身获取读锁的次数,具体参照源码的tryAcquireShared,仔细阅读并结合上面对写锁获取的分析不难读懂。

读锁的释放值得注意的地方在于自身维护的获取锁的次数,以及通过移位操作减少状态state – (1

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java连接字符串方法汇总
java连接字符串方法汇总

本专题整合了java连接字符串教程合集,阅读专题下面的文章了解更多详细操作。

6

2026.02.05

java中fail含义
java中fail含义

本专题整合了java中fail的含义、作用相关内容,阅读专题下面的文章了解更多详细内容。

8

2026.02.05

控制反转和依赖注入区别
控制反转和依赖注入区别

本专题整合了控制反转和依赖注入区别、解释、实现方法相关内容。阅读专题下面的文章了解更多详细教程。

9

2026.02.05

钉钉脑图插图教程合集
钉钉脑图插图教程合集

本专题整合了钉钉脑图怎么插入图片、钉钉脑图怎么用相关教程,阅读专题下面的文章了解更多详细内容。

19

2026.02.05

python截取字符串方法汇总
python截取字符串方法汇总

本专题整合了python截取字符串方法相关合集,阅读专题下面的文章了解更多详细内容。

2

2026.02.05

Java截取字符串方法合集
Java截取字符串方法合集

本专题整合了Java截取字符串方法汇总,阅读专题下面的文章了解更多详细操作教程。

1

2026.02.05

java 抽象方法
java 抽象方法

本专题整合了java抽象方法定义、作用教程等内容,阅读专题下面的文章了解更多详细内容。

2

2026.02.05

Eclipse创建jsp文件教程合集
Eclipse创建jsp文件教程合集

本专题整合了Eclipse创建jsp文件、创建jsp项目等等内容,阅读专题下面的文章了解更多详细教程。

21

2026.02.05

java 字符串转数字
java 字符串转数字

本专题整合了java如何字符串转数字相关内容,阅读专题下面的文章了解更多详细教程。

4

2026.02.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.2万人学习

C# 教程
C# 教程

共94课时 | 8.6万人学习

Java 教程
Java 教程

共578课时 | 58万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号