zoukankan      html  css  js  c++  java
  • ReentrantLock和ReentrantReadWriteLock

    上一篇已经将Lock锁的基础AQS简单地过了一遍了,因此本篇主要是讲解Lock锁主要的两个子类:

    • ReentrantLock
    • ReentrantReadWriteLock

    一、ReentrantLock锁

    • 比synchronized更有伸缩性(灵活)
    • 支持公平锁(是相对公平的)
    • 使用时最标准用法是在try之前调用lock方法,在finally代码块释放锁
    class X {
        private final ReentrantLock lock = new ReentrantLock();
        // ...
    
        public void m() { 
            lock.lock();  // block until condition holds
            try {
                // ... method body
            } finally {
                lock.unlock()
            }
        }
    }

    1.1内部类

    首先我们可以看到有三个内部类:

    这些内部类都是AQS的子类,这就印证了我们之前所说的:AQS是ReentrantLock的基础,AQS是构建锁、同步器的框架

    • 可以很清晰的看到,我们的ReentrantLock锁是支持公平锁和非公平锁的
    • 默认是非公平锁

    1.2非公平lock方法

    尝试获取锁,获取失败的话就调用AQS的acquire(1)方法

    1.3公平lock方法

    公平的lock方法其实就多了一个状态条件:

    这个方法主要是判断当前线程是否位于CLH同步队列中的第一个。如果是则返回flase,否则返回true。

    1.4unlock方法

    unlock方法也是在AQS中定义的:

    二、ReentrantReadWriteLock

    我们知道synchronized内置锁和ReentrantLock都是互斥锁(一次只能有一个线程进入到临界区(被锁定的区域))

    而ReentrantReadWriteLock是一个读写锁:

    • 在读取数据的时候,可以多个线程同时进入到到临界区(被锁定的区域)
    • 在写数据的时候,无论是读线程还是写线程都是互斥的

    一般来说:我们大多数都是读取数据得多,修改数据得少。所以这个读写锁在这种场景下就很有用了!

    读写锁有一个接口ReadWriteLock,定义的方法就两个:

    在读的时候可以共享,在写的时候是互斥的

    我们可以总结出读写锁的一些要点:

    • 读锁不支持条件对象,写锁支持条件对象
    • 读锁不能升级为写锁,写锁可以降级为读锁
    • 读写锁也有公平和非公平模式
    • 读锁支持多个读线程进入临界区,写锁是互斥的

    2.1ReentrantReadWriteLock内部类

    ReentrantReadWriteLock比ReentrantLock锁多了两个内部类(都是Lock实现)来维护读锁和写锁,但是主体还是使用Syn:

    • WriteLock
    • ReadLock

    2.2读锁和写锁的状态表示

    在ReentrantLock锁上使用的是state来表示同步状态(也可以表示重入的次数),而在ReentrantReadWriteLock是这样代表读写状态的:

    2.3写锁的获取

    主要还是调用syn的acquire(1):

    2.4读锁获取

    写锁的获取调用的是acquireShared(int arg)方法:

    三、最后

    这里就简单总结一下本文的内容吧:

    • AQS是ReentrantReadWriteLock和ReentrantLock的基础,因为默认的实现都是在内部类Syn中,而Syn是继承AQS的~
    • ReentrantReadWriteLock和ReentrantLock都支持公平和非公平模式,公平模式下会去看FIFO队列线程是否是在队头,而非公平模式下是没有的
    • ReentrantReadWriteLock是一个读写锁,如果读的线程比写的线程要多很多的话,那可以考虑使用它。它使用state的变量高16位是读锁,低16位是写锁
    • 写锁可以降级为读锁,读锁不能升级为写锁
    • 写锁是互斥的,读锁是共享的。
  • 相关阅读:
    函数模板的局限性级解决方法(第三代具体化)
    模板实现机制
    函数模板与普通函数的区别以及调用规则
    函数模板基本用法及泛型
    向上类型转换和向下类型转换
    虚析构和纯虚析构
    纯虚函数和抽象类
    多态原理
    静态联编和动态联编即多态的概念
    虚基类的内部工作原理
  • 原文地址:https://www.cnblogs.com/harpoonJava/p/13253484.html
Copyright © 2011-2022 走看看