多线程学习(七)-读写锁(ReentrantReadWriteLock)与应用(缓存)

2024-05-09 23:48

本文主要是介绍多线程学习(七)-读写锁(ReentrantReadWriteLock)与应用(缓存),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

读写锁ReentrantReadWriteLock分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!

读写锁机制

     -读不互斥

     -写互斥

     -写互斥

如果只读数据,可以多个线程读,但是不能同时有写的线程,上读锁

如果需要写数据,则不能有读的线程,且只能有一个线程写数据,上写锁。(如果上了读锁,需要先释放读锁)

线程进入读锁的前提条件:

    没有其他线程的写锁,

    没有写请求或者有写请求,但调用线程和持有锁的线程是同一个

线程进入写锁的前提条件:

    没有其他线程的读锁

    没有其他线程的写锁

1、示例

import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLock {public static void main(String[] args) {final Queue3 queue=new Queue3();for (int i = 0; i < 3; i++) {new Thread(new Runnable() {@Overridepublic void run() {while(true){queue.read();}}}).start();new Thread(new Runnable() {@Overridepublic void run() {while(true){int data=new Random().nextInt(1000);queue.write(data);}}}).start();}}
}
class Queue3{private int data;private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();public void read() {rwl.readLock().lock();try {System.out.println(Thread.currentThread().getName() + " be ready to read data!");Thread.sleep((long)(Math.random()*1000));System.out.println(Thread.currentThread().getName() + "have read data :" + data);} catch (Exception e) {e.printStackTrace();}finally{rwl.readLock().unlock();}}public void write(int data) {rwl.writeLock().lock();try {System.out.println(Thread.currentThread().getName() + " be write to write data!");Thread.sleep((long)(Math.random()*1000));this.data=data;System.out.println(Thread.currentThread().getName() + "have write data :" + data);} catch (Exception e) {e.printStackTrace();}finally{rwl.writeLock().unlock();}}}

实例公有三个线程读,三个线程写数据,当读取的时候,可以有多个线程去读取数据,但是如果有线程去写数据的时候,只有等到数据写完成之后,才能读数据。

2、应用

 缓存系统

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class CacheDemo {private Map<String, Object> cache = new HashMap<String, Object>();private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();public Object getData(String key) {rwl.readLock().lock();Object value = null;try {value = cache.get(key);if (value == null) {rwl.readLock().unlock();//必须先释放读锁,才能获取写锁rwl.writeLock().lock();try {if (value==null) {//获取写锁后再次判断对象是否为null,是为了当前等待的写线程不在执行赋值,直接取缓存数据value = "aaa";// 实际queryDB()cache.put(key,value);}} finally {rwl.writeLock().unlock();}rwl.readLock().lock();}} catch (Exception e) {e.printStackTrace();} finally {rwl.readLock().unlock();}return value;}
}

HashMap作为缓存是非线程安全的,事例使用读写锁的读锁和写锁来保证拿到的缓存cache是线程安全的。在读操作 get()时,需先上读锁,这样并发访问读时不会被阻塞。写操作在更新缓存cache必须提前获取写锁, 当写锁被获取后,其他线程对于读锁和写锁的获取均被阻塞,而只有写锁被释放 之后,其他读写操作才能继续

 


这篇关于多线程学习(七)-读写锁(ReentrantReadWriteLock)与应用(缓存)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/974834

相关文章

CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比

《CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比》CSS中的position属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布... css 中的 position 属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布局和层叠关

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Python使用Tkinter打造一个完整的桌面应用

《Python使用Tkinter打造一个完整的桌面应用》在Python生态中,Tkinter就像一把瑞士军刀,它没有花哨的特效,却能快速搭建出实用的图形界面,作为Python自带的标准库,无需安装即可... 目录一、界面搭建:像搭积木一样组合控件二、菜单系统:给应用装上“控制中枢”三、事件驱动:让界面“活”

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

Java实现本地缓存的常用方案介绍

《Java实现本地缓存的常用方案介绍》本地缓存的代表技术主要有HashMap,GuavaCache,Caffeine和Encahche,这篇文章主要来和大家聊聊java利用这些技术分别实现本地缓存的方... 目录本地缓存实现方式HashMapConcurrentHashMapGuava CacheCaffe

ShardingSphere之读写分离方式

《ShardingSphere之读写分离方式》:本文主要介绍ShardingSphere之读写分离方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录ShardingSphere-读写分离读写分离mysql主从集群创建 user 表主节点执行见表语句项目代码读写分

如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)

《如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)》:本文主要介绍如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)问题,具有很好的参考价值,希望对大家有所帮助,如有... 目录先在你打算存放的地方建四个文件夹更改这四个路径就可以修改默认虚拟内存分页js文件的位置接下来从高级-

PyCharm如何更改缓存位置

《PyCharm如何更改缓存位置》:本文主要介绍PyCharm如何更改缓存位置的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录PyCharm更改缓存位置1.打开PyCharm的安装编程目录2.将config、sjsystem、plugins和log的路径