ReentrantReadWriteLock读写锁的使用

本文深入解析ReentrantReadWriteLock,一种支持多个读线程同时访问但限制写操作的锁机制,适用于读多写少的场景,有效提升并发性能。文章详细介绍了读写锁的工作原理、特性及应用场景,并通过实例演示了其在实际编程中的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

读写锁概述

​ ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个读线程同时访问,但不允许写线程和读线程、写线程和写线程同时访问。相对于排他锁,提高了并发性。
在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。
读写锁内部维护了两个锁,一个用于读操作,一个用于写操作。所有 ReadWriteLock实现都必须保证 writeLock操作的内存同步效果也要保持与相关 readLock的联系。也就是说,成功获取读锁的线程会看到写入锁之前版本所做的所有更新。
ReentrantReadWriteLock支持以下功能:
支持公平与非公平的获取锁方式。
1.支持可重入,读线程获取读锁后还可以获取读锁,但是不能获取写锁;写线程获取写锁后既可以再次获取写锁还可以获取读锁。
2.允许从写锁降级为读锁,其实现方式是:先获取写锁,然后获取读锁,最后释放写锁。但是,从读锁升级到写锁是不可以的;
3.读取锁和写入锁都支持锁获取期间的中断;
4.Condition支持。仅写入锁提供了一个 Conditon 实现;读取锁不支持 Conditon ,readLock().newCondition() 会抛出 UnsupportedOperationException。

读写锁的使用

class ReentrantReadTest{
    private volatile Map<String,String> map=new HashMap<>();
    //创建读写锁
    private ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
    //读写锁也可以这样声明
    private Lock w=rwl.writeLock();
    private Lock r=rwl.readLock();
    //写方法
    public void setMapVla(String str1,String str2){
    	//加写锁
        rwl.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"开始写入");
            TimeUnit.SECONDS.sleep(3);
            map.put(str1,str2);
            System.out.println(Thread.currentThread().getName()+"写入完毕");
        } catch(Exception e) {
            e.printStackTrace();
        }finally {
        //释放写锁
            rwl.writeLock().unlock();
        }
    }
    //读方法
    public void getMapVla(String str1){
    	//加读锁
        rwl.readLock().lock();
        try {
           System.out.println(Thread.currentThread().getName()+"开始读");
            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName()+"读到"+map.get(str1));
        } catch(Exception e) {
            e.printStackTrace();
        }finally {
        //释放读锁
        rwl.readLock().unlock();
        }
    }
}

测试

public class ReentrantReadWriteLockTest {
    public static void main(String[] args) {
        ReentrantReadTest reentrantReadTest=new ReentrantReadTest();
        for (int i = 1; i <=10; i++) {
            final String tmpl=i+"";
            new Thread(()->{
            //修改线程
                reentrantReadTest.setMapVla(tmpl,tmpl);
            },tmpl).start();
        }
        for (int i = 1; i <=10; i++) {
            final String tmpl=i+"";
            new Thread(()->{
            //读取线程
                reentrantReadTest.getMapVla(tmpl);
            },tmpl).start();
        }
    }
}

运行结果

1开始写入
1写入完毕
2开始写入
2写入完毕
3开始写入
3写入完毕
4开始写入
4写入完毕
5开始写入
5写入完毕
6开始写入
6写入完毕
7开始写入
7写入完毕
8开始写入
8写入完毕
9开始写入
9写入完毕
10开始写入
10写入完毕
1开始读
3开始读
4开始读
5开始读
2开始读
7开始读
6开始读
10开始读
9开始读
8开始读
5读到5
6读到6
2读到2
7读到7
3读到3
4读到4
1读到1
9读到9
10读到10
8读到8

优点:解决了读写不能同时操作的问题,在不影响读的高并发情况下,保证了写的线程安全性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值