zoukankan      html  css  js  c++  java
  • 读写锁 ReadWriteLock

    在没有读写锁之前,假设使用普通的 ReentrantLock,那么虽然保证了线程安全,但是也浪费了一定的资源,因为如果多个读操作同时进行,其实并没有线程安全问题,可以允许让多个读操作并行,以便提高程序效率。

    但是写操作不是线程安全的,如果多个线程同时写,或者在写的同时进行读操作,便会造成线程安全问题。

    读写锁就解决了这样的问题,它设定了一套规则,既可以保证多个线程同时读的效率,同时又可以保证有写入操作时的线程安全。

    整体思路是它有两把锁,第 1 把锁是写锁,获得写锁之后,既可以读数据又可以修改数据,而第 2 把锁是读锁,获得读锁之后,只能查看数据,不能修改数据。读锁可以被多个线程同时持有,所以多个线程可以同时查看数据。

    在读的地方合理使用读锁,在写的地方合理使用写锁,灵活控制,可以提高程序的执行效率。

    读写锁的获取规则

    在使用读写锁时遵守下面的获取规则:

    • 如果有一个线程已经占用了读锁,则此时其他线程如果要申请读锁,可以申请成功。

    • 如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁,因为读写不能同时操作。

    • 如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,都必须等待之前的线程释放写锁,同样也因为读写不能同时,并且两个线程不应该同时写。

    所以我们可以总结为:读读共享、其他都互斥(写写互斥、读写互斥、写读互斥)。

    使用案例

    下面举个例子来应用读写锁,ReentrantReadWriteLock 是 ReadWriteLock 的实现类,最主要的有两个方法:readLock() 和 writeLock() 用来获取读锁和写锁。

    代码如下:

    /**
     * 描述:     演示读写锁用法
     */
    public class ReadWriteLockDemo {
    ​
    ​
        private static final ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(false);
        private static final ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
        private static final ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock .writeLock();
    ​
    ​
        private static void read() {
            readLock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "得到读锁,正在读取");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                readLock.unlock();
                System.out.println(Thread.currentThread().getName() + "释放读锁");
            }
        }
    ​
    ​
        private static void write() {
            writeLock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "得到写锁,正在写入");
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                writeLock.unlock();
                System.out.println(Thread.currentThread().getName() + "释放写锁");
            }
        }
    ​
        public static void main(String[] args) throws InterruptedException {
            new Thread(() -> read()).start();
            new Thread(() -> read()).start();
            new Thread(() -> write()).start();
            new Thread(() -> write()).start();
        }

    程序的运行结果是:

    Thread-0得到读锁,正在读取
    Thread-1得到读锁,正在读取
    Thread-0释放读锁
    Thread-1释放读锁
    Thread-2得到写锁,正在写入
    Thread-2释放写锁
    Thread-3得到写锁,正在写入
    Thread-3释放写锁
    可以看出,读锁可以同时被多个线程获得,而写锁不能。

    读写锁适用场合

    相比于 ReentrantLock 适用于一般场合,ReadWriteLock 适用于读多写少的情况

  • 相关阅读:
    flask框架+上传文件接口实战【软件测试培训】【多测师_王sir】
    读取Excel中的视频文件地址+requests库下载后存入本地文件夹【软件测试培训】【多测师_王sir】
    UI和接口自动化中的设计模式:单例模式【软件测试培训】【多测师_王sir】
    Python+BeautifulReport生成完美的接口自动化测试报告【多测师_王sir】
    Linux命令中查找以.log结尾文件中不包含某个特定字符串这行的内容【多测师_王sir】
    查询多条数据
    django登录装饰接口封装
    django使用redis作为session缓存
    tinymce配置
    django重写authcenticate方法兼容用户、邮箱、密码认证登录
  • 原文地址:https://www.cnblogs.com/zz-ksw/p/12774151.html
Copyright © 2011-2022 走看看