java并发编程中ReentrantLock可重入读写锁

 更新时间:2022年05月15日 09:22:10   作者:字母哥博客  
这篇文章主要介绍了java并发编程中ReentrantLock可重入读写锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、ReentrantLock可重入锁

可重入锁ReentrantLock 是一个互斥锁,即同一时间只有一个线程能够获取锁定资源,执行锁定范围内的代码。这一点与synchronized 关键字十分相似。其基本用法代码如下:

Lock lock = new ReentrantLock();  //实例化锁
//lock.lock(); //上锁
boolean locked = lock.tryLock();  //尝试上锁
if(locked){
  try {
    //被锁定的同步代码块,同时只能被一个线程执行
  }finally {
    lock.unlock(); //放在finally代码块中,保证锁一定会被释放
  }
}

通过lock函数获取锁,通过unlock函数释放锁。非常重要的是,需要把需要同步执行的代码放入 try/finally 代码块中,并在finally中将锁释放。ReentrantLock是可重入锁,即:(lock/unlok)动作里面可以嵌套(lock/unlock),针对同一个锁可以多次嵌套使用,不会产生死锁。但是lock函数与unlock函数在代码中必须成对出现,否则会出现死锁

二、ReentrantReadWriteLock读写锁

ReentrantReadWriteLock类为读写锁实现类,针对某一个对象或可变变量,只要没有线程在修改它,这个对象或可变变量就可以同时被多个线程读取。ReentrantReadWriteLock将锁分为读锁和写锁,只要没有线程持有写锁的情况下,读锁可以由多个线程同时持有。

  • 读锁-如果没有线程获取或请求写锁,那么多个线程可以获取读锁
  • 写锁-如果没有线程在读或写,那么只有一个线程可以获得写锁

简单的说就是ReentrantReadWriteLock可以保证最多同时有一个线程在写数据,或者可以同时有多个线程读数据。因此使用ReentrantReadWriteLock,在读操作比写操作更频繁的情况下,可以提高程序的性能和吞吐量。

下面我们用一个简单的例子,来解读一下如何应用读写锁。

public class TestReadWriteLock {
  //可以同时执行3个线程任务的线程池
  ExecutorService executor = Executors.newFixedThreadPool(3);
  //读写目标,写线程放入数据到map,读线程从map读取数据
  Map<String, String> map = new HashMap<>();
  //读写锁操作对象
  ReadWriteLock lock = new ReentrantReadWriteLock();

  //写操作函数
  public void write(){
    executor.submit(() -> { //线程池提交写操作任务
      lock.writeLock().lock(); //加写锁
      try {
        map.put("key", "val");  //写数据操作
        Thread.sleep(2000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
        lock.writeLock().unlock(); //释放写锁
      }
    });
  }

  //读操作函数
  public void read(){
    lock.readLock().lock(); //加读锁
    System.out.println(Thread.currentThread().getName() + "加读锁");
    try {
      System.out.println(map.get("key")); //读数据操作
    } finally {
      lock.readLock().unlock(); //释放读锁
      System.out.println(Thread.currentThread().getName() + "释放读锁");
    }
  }

}

三、读锁之间不互斥

我们写一个测试方法,通过打印输出来理解读写锁控制代码的执行顺序。

  //测试
  public static void main(String[] args) {
    TestReadWriteLock test = new TestReadWriteLock();
    test.write();  //提交一次写操作任务,写一条数据
    Runnable readTask = test::read;  //线程方法read,实现线程Runnable接口的简便写法
    test.executor.submit(readTask);  //读1次(新读线程)
    test.executor.submit(readTask);  //读2次 (新读线程)
    test.executor.shutdown();
  }

执行上面的代码,可能会出现下面的输出

pool-1-thread-2加读锁
pool-1-thread-3加读锁
val
val
pool-1-thread-3释放读锁
pool-1-thread-2释放读锁

在pool-1-thread-2没有释放读锁情况下,pool-1-thread-3可以再次加读锁,并且都正确的读取到数据val。说明读锁之间是不互斥的。但是,在进行读操作(读锁生效)的时候,写操作是无法进行的(无法获取写锁),所以ReentrantReadWriteLock不支持同时加读锁和写锁。 这个结论我可以负责任告诉大家,这里我就不做验证了!

到此这篇关于java并发编程中ReentrantLock可重入读写锁的文章就介绍到这了,更多相关java ReentrantLock可重入读写锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring+SpringMVC+MyBatis深入学习及搭建(三)之MyBatis全局配置文件解析

    Spring+SpringMVC+MyBatis深入学习及搭建(三)之MyBatis全局配置文件解析

    这篇文章主要介绍了Spring+SpringMVC+MyBatis深入学习及搭建(三)之MyBatis全局配置文件解析,需要的朋友可以参考下
    2017-05-05
  • 从dubbo源码分析qos-server端口冲突问题及解决

    从dubbo源码分析qos-server端口冲突问题及解决

    这篇文章主要介绍了从dubbo源码分析qos-server端口冲突问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Java避免UTF-8的csv文件打开中文出现乱码的方法

    Java避免UTF-8的csv文件打开中文出现乱码的方法

    这篇文章主要介绍了Java避免UTF-8的csv文件打开中文出现乱码的方法,结合实例形式分析了java操作csv文件时使用utf-16le编码与utf8编码相关操作技巧,需要的朋友可以参考下
    2019-07-07
  • Java代码实现循环队列的示例代码

    Java代码实现循环队列的示例代码

    队列作为基础的数据结构,是程序员的入门课。也是所有程序员必须掌握的一种数据结构,队列在程序中广泛应用,因此我们应该对队列有深入的了解,接下来我们通过代码来对队列这种数据结构进行深度解析,感兴趣的朋友一起看看吧
    2021-09-09
  • springboot整合freemarker详解

    springboot整合freemarker详解

    本篇文章主要介绍了springboot整合freemarker详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 详解Java中方法重写与重载的区别(面试高频问点)

    详解Java中方法重写与重载的区别(面试高频问点)

    这篇文章主要介绍了Java中方法重写与重载的区别(面试高频问点),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • SpringBoot下如何实现支付宝接口的使用

    SpringBoot下如何实现支付宝接口的使用

    这篇文章主要介绍了SpringBoot下如何实现支付宝接口的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Java实现的简单数字时钟功能示例

    Java实现的简单数字时钟功能示例

    这篇文章主要介绍了Java实现的简单数字时钟功能,涉及java日期时间及JFrame框架图形界面操作相关实现技巧,需要的朋友可以参考下
    2019-02-02
  • Java利用POI读写Excel文件工具类

    Java利用POI读写Excel文件工具类

    这篇文章主要为大家详细介绍了Java利用POI读写Excel文件的工具类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • Mybatis Generator最完美配置文件详解(完整版)

    Mybatis Generator最完美配置文件详解(完整版)

    今天小编给大家整理了一篇关于Mybatis Generator最完美配置文件详解教程,非常不错具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-11-11

最新评论