JUC-ReentrantReadWriteLock锁基础篇

JUC-AQS原理篇
JUC-AQS源码篇
JUC-AQS的Condition之await和signal源码解析

JUC-CountDownLatch基础篇
JUC-CountDownLatch源码分析
JUC-Semaphore基础篇
JUC-Semaphore源码分析
JUC-ReentrantReadWriteLock锁基础篇
JUC-ReentrantReadWriteLock锁源码分析
JUC-ReentrantLock锁基础篇
JUC-ReentrantLock锁源码分析
JUC-CyclicBarrier基础篇
JUC-CyclicBarrier源码分析

1.概念

ReentrantReadWriteLock是一种读写锁,它与ReentrantLock的用法才不多,那么为啥还要有读写锁呢。
在业务开发中我们会遇到读写操作,面对读写的数据同步,我们用ReentrantLock锁就可以实现了,但是在实际的读写业务场景中还是读的操作多,写的操作少,那么ReentrantLock锁的效率就会显的很低下。因为无论是读还是写操作,ReentrantLock都要去获取锁。也就是读写互斥,读读也是互斥的。但是我们知道读读互斥其实是不用的,因为我们使用锁的初衷是为了保证数据的同步。读又不会改变数据,所有ReentrantReadWriteLock就诞生了。
ReentrantReadWriteLock是一种读写锁。
在不同线程中:它们读写是互斥的,写写也是互斥的。但是读读却不是互斥了。一个线程获取了一把读锁,另外一把线程也可以获取这把读锁。
在同一个线程中:由于ReentrantReadWriteLock也是可重入的,所以读线程在获取了读锁后还可以获取读锁,但是不能获取写锁;写线程在获取了写锁之后既可以再次获取写锁又可以获取读锁。
ReentrantReadWriteLock的特性,基本与ReentrantLock一致,具体特性用法可以参考ReentrantLock锁:
1.可重入的。
2.支持公平和非公平的获取锁的方式
3.支持超时或者响应中断的,读取锁和写入锁都支持锁获取期间的中断
4.Condition支持,仅写入锁提供了Condition实现,读取锁不支持Condition,readLock().newCondition()会抛出异常。
5.ReentrantReadWriteLock是依赖AQS来实现的
6.与ReentrantLock最大的不同点是,ReentrantLock是独占锁,而ReentrantReadWriteLock不是。
7.有读锁与写锁这两把锁。而ReentrantLock只是一把锁。

2.常用方法

方法说明
readLock()获取一把读锁
writeLock()获取一把写锁

读锁的常用方法

方法说明
lock()获取一把读锁。在不同线程中如果有其他的线程获取了写锁,则进入同步队列阻塞,否则获取到这把读锁。在同一个线程中,如果之前获取了写锁,则可以接着获取,如果之前获取了读锁,则不能获取这把写锁
unlock()当前线程释放这把读锁
lockInterruptibly()与lock一致,但是如果当前线程在阻塞的过程中,别其他的线程中断了,则会抛出中断异常
tryLock()只是尝试的来获取读锁,获取到了返回true 获取不到返回false
tryLock(long timeout, TimeUnit unit)只是尝试的来获取读锁,获取到了返回true ,在指定的时间内还是获取不到,则返回false
newCondition读锁,没有实现,调用会抛出UnsupportedOperationException异常

写锁的常用方法

方法说明
lock()获取一把写锁。在不同线程中如果有其他的线程获取了写或者读锁,则进入同步队列阻塞,否则获取到这把写锁。在同一个线程中,可以直接获取到这把锁
unlock()当前线程释放这把写锁
lockInterruptibly()与lock一致,但是如果当前线程在阻塞的过程中,别其他的线程中断了,则会抛出中断异常
tryLock()只是尝试的来获取写锁,获取到了返回true 获取不到返回false
tryLock(long timeout, TimeUnit unit)只是尝试的来获取写锁,获取到了返回true ,在指定的时间内还是获取不到,则返回false
newCondition生成一个等待集合Condition对象

3.举例

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Description:
 * @Package PACKAGE_NAME
 * @Author Zhai Quanjiang
 * @Date 2022/6/7 10:25
 * @Version: V1.0
 * @Other:
 */
public class ReentrantReadWriteLockTest {
    public static void main(String[] args) throws InterruptedException {
        test1();
    }

    public static void test1(){
        ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
        Thread thread1 = new Thread("thread1") {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "准备获取读锁");
                reentrantReadWriteLock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "获取了读锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }
                System.out.println(Thread.currentThread().getName() + "释放了读锁");
                reentrantReadWriteLock.readLock().unlock();
            }
        };
        Thread thread2 = new Thread("thread2") {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "准备获取读锁");
                reentrantReadWriteLock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "获取了读锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }
                System.out.println(Thread.currentThread().getName() + "释放了读锁");
                reentrantReadWriteLock.readLock().unlock();
            }
        };
        Thread thread3 = new Thread("thread3") {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "准备获取写锁");
                reentrantReadWriteLock.writeLock().lock();
                System.out.println(Thread.currentThread().getName() + "获取了写锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }
                System.out.println(Thread.currentThread().getName() + "释放了写锁");
                reentrantReadWriteLock.writeLock().unlock();
            }
        };
        Thread thread4 = new Thread("thread4") {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "准备获取读锁");
                reentrantReadWriteLock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "获取了读锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }
                System.out.println(Thread.currentThread().getName() + "释放了读锁");
                reentrantReadWriteLock.readLock().unlock();
            }
        };
        //线程thread1获取读锁
        thread1.start();
        //线程thread2获取读锁
        thread2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {

        }
        //线程thread3获取写锁,由于前面已经获取了读锁所以此时阻塞住
        thread3.start();
        //线程thread4获取读锁
        thread4.start();
    }
}

执行结果
执行结果
从上面结果可以看出,在线程thread1获取了读锁的情况下,线程thread2,thread4还可以获取读锁。而线程thread3不能获取写锁,要等读锁全部释放掉,才能获取

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值