zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java多线程之ReentrantReadWriteLock

2023-09-27 14:29:33 时间

        一、锁的种类和含义        

        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的逻辑。