Java多线程之ReentrantReadWriteLock
一、锁的种类和含义
Java的concurrent并发包中,存在两种类型的锁,即共享锁和排它锁,后者也叫做独占锁。
共享锁是指某一时刻锁可以被多个线程同时拥有,这些线程同时共享该锁。而排它锁则是指锁在某一时刻只能被一个线程拥有,任何想要获得该锁的线程,必须等待的锁的所有者释放后才可以。
二、ReentrantReadWriteLock的含义
ReentrantReadWriteLock是Java中的一种读写锁,它既不是完全的共享锁,也不是完全的排它锁。它实际上是一种混合形式的锁,既包含共享锁,同时也包含排它锁。
这么做是为了什么呢?我们知道,很多情况下有这样一种业务场景,即对于一块数据,或者一个对象,即存在需要读取的时候,也存在需要修改,即写入的时候。那么,如果对于这种应用场景,如果是只用共享锁,同一时刻,允许多个线程读取和写入数据,那么数据操作的原子性就无法得到保证,在多并发的情况下,数据往往就是紊乱的;如果是只用排它锁,即某一线程读取的时候,即不允许其它线程写入,也不允许其它线程读取,这样是能保证数据操作的原子性,得到正确的数据,那么性能也随之降低了。
所以,在兼顾数据操作的原子性和读写性能二者的情况下,一种同时融合共享锁和排它锁的混合锁的产生,就显得特别有意义了。这就是我们本文将要阐述的读写锁ReentrantReadWriteLock。
它在读取数据或对象的时候使用读锁,即一种对读共享同时读写排它的锁,允许多个线程同时读取数据,但是不允许其它线程修改数据;而在修改数据或对象时使用写锁,一种完全的排它锁,既不允许 其它线程读取数据,也不允许其他线程修改数据。这样,数据操作的原子性和性能同时得到了考虑。
三、ReentrantReadWriteLock的定义及实现
ReentrantReadWriteLock实现了Java中的ReadWriteLock接口。
四、ReentrantReadWriteLock的使用方式及代码示例
ReentrantReadWriteLock的使用方式如下:
首先,需要构造一个ReentrantReadWriteLock对象rrwl。代码如下:
// 构造ReentrantReadWriteLock对象rrwl private ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();其次,需要获取ReentrantReadWriteLock对象rrwl的读锁readLock和写锁writeLock。代码如下:
// 获取读锁readLock:可被多个读线程共享,但是会排斥所有的写线程 private Lock readLock = rrwl.readLock(); // 获取写锁writeLock:排斥所有的读线程和其它写线程 private Lock writeLock = rrwl.writeLock();然后,读锁的使用方法如下:
// 读锁的使用 public Object readObject() { Object object = null; // 利用读锁readLock获取读锁 readLock.lock(); try { // 此处为业务代码 object = new Object(); } finally { // 利用读锁readLock释放读锁 readLock.unlock(); return object; }最后,写锁的使用方法如下:
// 写锁的使用 public void writeObject(Object object) { // 利用写锁writeLock获取写锁 writeLock.lock(); try { // 此处为业务代码 } finally { // 利用写锁writeLock释放写锁 writeLock.unlock(); }
Java多线程之线程池 1. 线程池的作用 2. 使用线程池的好处 3. 线程池的七个参数 4. 线程池执行任务的流程 5. Java 标准库中的线程池 1)newFixedThreadPool 2)newCachedThreadPool 3)newScheduleThreadPool 4)newSingleThreadExecutor 6. 对比两种提交任务的方法
这篇文章主要从源码角度讲解ReentrantReadWriteLock的ReadLock的加锁和减锁过程。 ReentrantReadWriteLock的ReadLock加锁解锁过程依赖于AQS类,所以有些相同的逻辑可以看看ReentrantLock的逻辑。
这篇文章主要从源码角度讲解ReentrantReadWriteLock的WriteLock的加锁和减锁过程。 ReentrantReadWriteLock的WriteLock加锁解锁过程依赖于AbstractQueuedSynchronizer(AQS)类,所以有些相同的逻辑可以看看ReentrantLock的逻辑。
相关文章
- Java计算机IT编程文档常见单词翻译
- 学了这么久的高并发编程,连Java中的并发原子类都不知道?
- java多线程执行问题
- java多线程,如何防止脏读数据
- java多线程基础(一)
- java文件同步性能测试
- xubuntu14.04下编译pjsip及pjsua2 java
- 恒生电子java开发工资,面试经历分享
- Java Maven编译时没问题,运行时报java.lang.NoSuchMethodError
- JAVA多线程suspend()、resume()和wait()、notify()的区别
- Java虚拟机的内存结构
- Java多线程干货系列—(四)volatile关键字
- java多线程并发控制countDownLatch和cyclicBarrier的使用
- Call to localhost/127.0.0.1:9000 failed on connection exception:java.net.ConnectException的解决方案
- JAVA RandomAccessFile writeBytes
- 终于,我读懂了所有Java集合——map篇(多线程)
- Java多线程(一) synchronized同步方法
- 【 java 枚举类】java 枚举类
- Java 8 时间日期库的20个使用示例
- Java 使用(BufferedImage)ImageIO下载抓取多个图片合成pdf文件
- 推荐一款非常好用的java反编译工具(转)
- Java 并发/多线程教程(十一)-JAVA内存模型
- Java 记录(7)多线程使用(异步)
- 大数据必学Java基础(七十五):多线程与程序、进程、线程之间概念详解
- Java多线程-新特征-原子量
- Java多线程-线程的交互
- JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止
- 【jvm我能讲两小时029】说说你对java.lang.invoke包的理解,与反射调用的区别?