ReentrantReadWriteLock读写锁

这篇具有很好参考价值的文章主要介绍了ReentrantReadWriteLock读写锁。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ReentrantReadWriteLock读写锁

乐观锁和悲观锁

乐观锁

乐观锁,就是给需要共享的数据,添加一个版本号version,例如1,每次有线程更新共享数据后,version+1,每次线程进行数据更新时,要比较当前线程持有的数据的版本号,相等则修改,不相等则不修改,支持并发访问。

悲观锁

悲观锁,就是每次只能有一个线程,访问共享的数据,其他线程都阻塞,只有当前线程结束,才会释放锁,其他线程中的一个才能访问,不支持并发访问。

表锁和行锁

表锁

线程涉及到数据库的修改时,其他线程不能修改整个表中的任意行数据,就是表锁,表锁不会出现行锁。

行锁

线程涉及到数据库的修改时,只锁当前的一行,是行锁,可能会出现死锁。

读写锁

读锁是共享锁,写锁是独占锁。都可能出现死锁。
读写锁,一个资源可以被多个读线程访问,或者一个写线程访问,但是不能同时存在读写线程,读写是互斥的,读读是共享的。

案例及代码实现
//1.定义资源类
class MyCache {

    //volatile关键字,共享的数据,在一个线程修改后,被其他线程访问到
    private volatile HashMap<String, Object> hashMap = new HashMap<>();

    private ReadWriteLock rwLock = new ReentrantReadWriteLock();

    //2.定义操作资源类的方法
    public Object get(String key) {
        rwLock.readLock().lock();//读锁
        Object result = null;
        try {
            System.out.println(Thread.currentThread().getName() + "正在读取值" + key);

            TimeUnit.MILLISECONDS.sleep(300);
            result = hashMap.get(key);
            System.out.println(Thread.currentThread().getName() + "读取值完成" + key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rwLock.readLock().unlock();
        }
        return result;
    }

    public void put(String key, Object value) {
        rwLock.writeLock().lock();//写锁
        try {
            System.out.println(Thread.currentThread().getName() + "正在添加值" + key);
            TimeUnit.MILLISECONDS.sleep(300);
            hashMap.put(key, value);
            System.out.println(Thread.currentThread().getName() + "添加值完成" + key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rwLock.writeLock().unlock();
        }

    }


}

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache cache = new MyCache();
        
        //创建线程,向缓存中添加值
        for (int i = 0; i < 5; i++) {
            final int num = i;
            new Thread(() -> {
                cache.put(num + "", num);
            }, String.valueOf(i)).start();
        }

        //创建线程,向缓存中获取值
        for (int i = 0; i < 5; i++) {
            final int num = i;
            new Thread(() -> {
                cache.get(num + "");
            }, String.valueOf(i)).start();
        }

    }
}

读写锁的演变

ReentrantReadWriteLock读写锁

读写锁的降级

ReentrantReadWriteLock读写锁文章来源地址https://www.toymoban.com/news/detail-747221.html

降级案例及代码
/**
 * @author 长名06
 * @version 1.0
 * 读写锁降级演示
 */
public class ReadWriteLockDownLevelDemo {
    public static void main(String[] args) {
        ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();//写锁
        ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();//读锁
		//先读后写,获取读锁后,就获取不到写锁,线程阻塞

        //1.获取写锁
        writeLock.lock();
        System.out.println("获取写锁");

        //2.获取读锁
        readLock.lock();
        System.out.println("获取读锁");

        //3.释放写锁
        writeLock.unlock();

        //4.释放读锁
        readLock.unlock();
    }
}

小结

  • 1.在线程持有读锁的情况下,该线程不能取得写锁,因为获取写锁时,如果写锁对应的读锁被占用,就马上获取失败,不管读锁是否是当前线程持有(原因,此写锁对应的读锁被线程持有,证明有线程正在读取数据,这是为了避免出现幻读现象)。
  • 2.在线程持有写锁的情况下,该线程可以继续获取读锁。获取读锁时,如果发现写锁被占用,只有写锁没有被当前线程占用的情况下才会获取失败。
  • 原因,读锁是共享锁,即当某个线程获取读锁时,可能有其他线程同时也在持有读锁;而对于已获取写锁的线程,它一定独占了写锁因此可以继续让其获取读锁,当该线程同时获取了写锁和读锁时,还可以先释放写锁继续持有读锁,这样就称为写锁的降级。
    只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

到了这里,关于ReentrantReadWriteLock读写锁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【UE】读写配置文件 ue读写ini文件

    UE已经封装好了ini的读写功能,我们只需要简单几步就可以读写ini文件 这里我们选择Blueprint Function Library类型

    2024年02月11日
    浏览(62)
  • 【Python--XML文件读写】XML文件读写详解

    1.1 介绍 XML 指可扩展标记语言XML ,常被设计用来传输和存储数据。 XML 是一种固有的分层数据格式,最自然的表示方式是使用树。 ET为此有两个类 - ElementTree将整个 XML 文档表示为一棵树,并 Element表示该树中的单个节点。与整个文档的交互(从文件读取和写入/从文件写入)通

    2024年02月04日
    浏览(40)
  • Python用openpyxl操作Excel:读写、遍历、单元格读写

    openpyxl支持读写Excel,自带整合Pandas和NumPy功能。 worksheet cell

    2024年02月16日
    浏览(59)
  • 非常详细HDFS读写流程+完美视觉的HDFS读写流程图

    一、写数据流程: 客户端(Client通过java虚拟机)向NameNode请求上传文件(内部过程:客户端通过对 DistributedFileSystem 对象调用create()函数来创建文件),参数:路径/a.txt,块规格,副本数。 NameNode检查目标文件是否已存在,父目录是否存在。做出响应返回是否可以上传。 过程

    2024年02月04日
    浏览(64)
  • 07-1_Qt 5.9 C++开发指南_文件系统及文件读写_文本文件读写(使用 QTextStream 进行文件读写更为方便)

    文本文件是指以纯文本格式存储的文件,例如用 Qt Creator 编写的 C++程序的头文件 (.h 文件)和源程序文件 (.cpp 文件)。HTML 和 XML 文件也是纯文本文件,只是其读取之后需要对内容进行解析之后再显示。 Qt 提供了两种读写纯文本文件的基本方法, 一种是用 QFile 类的 IODevice 读写

    2024年02月13日
    浏览(56)
  • 寄存器内存读写指令(二) —— 多寄存器读写 LDM / STM

    有的时候,CPU可能会遇到 a++; b++; c++,这个时候为了提升效率,CPU可能会一次将多个寄存器里的变量保存到内存中。这个时候之前介绍的 LDR / STR 指令虽然也能实现,但只能操作一个寄存器的读写。 因此,考虑到这点,下面介绍多个寄存器的读写指令 将 多个寄存器 的数据写

    2024年02月07日
    浏览(60)
  • 利用 yaml-cpp 开源库读写 yaml 配置文件—— 读写部分

    Node 是 yaml-cpp 中的核心概念,是最重要的数据结构,它用于存储解析后的 yaml 信息。 Node一共有以下几种type: 1)Null 空节点 2)Sequence 序列,类似于一个Vector,对应YAML格式中的数组 3)Map 类似标准库中的Map,对应YAML格式中的对象 4)Scalar 标量,对应YAML格式中的常量 生成 N

    2024年02月10日
    浏览(46)
  • mysql面试题45:读写分离常见方案、哪些中间件可以实现读写分离

    该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 读写分离是一种常见的数据库架构方案,旨在分担数据库的读写压力,提高系统的性能和可扩展性。以下是两种常见的读写分离方案: 主从复制方案

    2024年02月07日
    浏览(45)
  • 【嵌入式Qt开发入门】如何使用Qt进行文本读写——QFile读写文本

            在很多时候我们需要读写文本文件进行读写,比如写个 Mp3 音乐播放器需要读 Mp3 歌词里的文本,比如修改了一个 txt 文件后保存,就需要对这个文件进行读写操作。本文介绍简单的文本文件读写,内容精简,让大家了解文本读写的基本操作。         QFile 类提

    2024年02月12日
    浏览(45)
  • 基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制

    基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制,模块接口清晰,可移植性高. 基于FPGA的DDR3读写控制是一项重要的技术,它为多通道图像数据的读写提供了高效的解决方案。本文将介绍一种纯Verilog实现的DDR3读写控制模块,旨在实现模块接口清晰、可移

    2024年04月12日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包