• JUC-ReentrantReadWriteLock锁基础篇


    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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

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

  • 相关阅读:
    2022-08-26 Unity视频播放1——视频介绍
    递归:深度优先搜索
    文件解析工具
    判断子序列 -- 二分查找
    idea集成本地tomcat
    c++后端开发-学习汇总
    excel怎么设置密码?加密文件这么做!
    idea配置git(gitee)并提交(commit)推送(push)
    【头歌-Python】8.5 中文词频统计(project) 1~5关
    【基于stm32f407应用】中断模式串口通讯-USART1
  • 原文地址:https://blog.csdn.net/zqj1172102457/article/details/125471570