Java多线程——读写锁ReentrantReadWriteLock

概述

ReentrantReadWriteLock,是一种读写锁,对读写操作的多线程访问提供了特殊处理,可以提高读取操作的性能,让读并发,写加锁。

  • 读操作可并发
  • 读写操作互斥
  • 写操作互斥

其原理与ReentrantLock基本一直,只不过加入了读写锁的逻辑,底层也是使用了AQS同步器,AQS的源码解析可查阅我的另一篇文章:Java多线程——JUC之AQS(AbstractQueuedSynchronizer)分析,ReentrantLock的实现原理解析

基本使用

package com.leolee.multithreadProgramming.juc.reentrantReadWriteLock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @ClassName Test
 * @Description: reentrantReadWriteLock,读写锁,可以提高读取操作的性能,让读并发,写加锁
 * @Author LeoLee
 * @Date 2021/3/7
 * @Version V1.0
 **/
@Slf4j
public class Test {

    public static void main(String[] args) {
        Test.test2();
    }

    /*
     * 功能描述: <br>
     * 〈验证读写锁——多线程【读】操作是否互斥〉
     * 结果:读写锁的读操作是不互斥的
     * @Param: []
     * @Return: void
     * @Author: LeoLee
     * @Date: 2021/3/7 13:55
     */
    public static void test1() {
        ReadWriteLock readWriteLock = new ReadWriteLock();
        new Thread(() -> {
            readWriteLock.read();
        }, "t1").start();
        new Thread(() -> {
            readWriteLock.read();
        }, "t2").start();
    }

    /*
     * 功能描述: <br>
     * 〈验证读写锁——多线程【读写】操作是否互斥〉
     * 结果:读写锁的读写操作是互斥的
     * @Param: []
     * @Return: void
     * @Author: LeoLee
     * @Date: 2021/3/7 13:55
     */
    public static void test2() {
        ReadWriteLock readWriteLock = new ReadWriteLock();
        new Thread(() -> {
            readWriteLock.read();
        }, "t1").start();
        new Thread(() -> {
            readWriteLock.write();
        }, "t2").start();
    }

}

@Slf4j
class ReadWriteLock {
    private Object data;

    private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    //读锁
    private ReentrantReadWriteLock.ReadLock readLock = rwl.readLock();
    //写锁
    private ReentrantReadWriteLock.WriteLock writeLock = rwl.writeLock();


    public Object read() {
        log.info("获取读锁...");
        readLock.lock();
        try {
            log.info("读取操作");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            log.info("释放读锁...");
            readLock.unlock();
        }
        return data;
    }

    public void write() {
        log.info("获取写锁...");
        writeLock.lock();
        try {
            log.info("写入操作");
        } finally {
            log.info("释放写锁...");
            writeLock.unlock();
        }
    }
}

注意事项:

  • 读锁不支持条件变量,也就是无法使用Condition
  • ReentrantReadWriteLock是可重入锁,但是不支持重入的锁升级,即有读锁的情况下去获取写锁,会导致获取写锁永久等待,发生死锁在持有写锁的情况下,是可以支持获取读锁的

Javadoc关于重入情况下,写锁降级为读锁的示例

* <pre> {@code
 * class CachedData {
 *   Object data;
 *   volatile boolean cacheValid;
 *   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
 *
 *   void processCachedData() {
 *     rwl.readLock().lock();
 *     if (!cacheValid) {
 *       // Must release read lock before acquiring write lock
 *       rwl.readLock().unlock();
 *       rwl.writeLock().lock();
 *       try {
 *         // Recheck state because another thread might have
 *         // acquired write lock and changed state before we did.
 *         if (!cacheValid) {
 *           data = ...
 *           cacheValid = true;
 *         }
 *         // Downgrade by acquiring read lock before releasing write lock
 *         rwl.readLock().lock();
 *       } finally {
 *         rwl.writeLock().unlock(); // Unlock write, still hold read
 *       }
 *     }
 *
 *     try {
 *       use(data);
 *     } finally {
 *       rwl.readLock().unlock();
 *     }
 *   }
 * }}</pre>

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值