JAVA读锁不使用效果一样_Java使用读写锁替代同步锁
应用情景
前一阵有个做反抄袭检测的小伙伴问了我一个问题。
---
在多线程里就是有个变量,我需要读取它来判断是否给它写入一些信息。
打算加锁,但是如果读取时候加入readlock,写入时候加入writelock,
这样做可能读写不同步。但是如果一起加lock效果就跟synchronized一样,效率变差
---
其实他的问题就是下面的场景:
高并发的读写请求
读取请求明显大于写入的请求
如果用synchronized同步锁会导致性能下降,本来读取是可以多线程同步进行的,同步锁就只能让他们一个一个排队读取。
如果读取时加readlock,写入时候加writelock,会提升效率,因为读可以多线程并发,但是在线程A读完上锁的毫秒级时间里,有可能线程B也读完了,而且抢在了线程A之前修改了变量,导致程序出错。
处理方案
我去研究了下读写锁,后来发现其实java官方已经给了答案。使用读写锁加标志位解决读写不同步的问题。Java ReentrantReadWriteLock
在这先普及下读写锁。
读锁:
读锁拒绝其他线程获得写锁,读锁不拒绝其他线程获得读锁,多个上了读锁的线程可以并发读不会阻塞。
多个读锁同时作用期间,其他想上写锁的线程都处在等待状态,当最后一个读锁释放后,才有可能上锁。
写锁:
写锁拒绝其他线程获取读锁和写锁。
当一个线程获取写锁后,其他想要获取读写锁的线程都处于等待状态,直到写锁释放才有可能上锁。
##代码实例
直接拿Java官方示例解读了。
classCachedData{Objectdata; volatile boolean cacheValid; final ReentrantReadWriteLock rwl =newReentrantReadWriteLock();voidprocessCachedData() { rwl.readLock().lock();//1. 上读锁if(!cacheValid) {//2. 验证cacheValid// Must release read lock before acquiring write lockrwl.readLock().unlock();//3. 解除读锁rwl.writeLock().lock();//4. 上写锁try{// Recheck state because another thread might have// acquired write lock and changed state before we did.if(!cacheValid) {//5. 验证cacheValiddata = ... cacheValid =true; }// Downgrade by acquiring read lock before releasing write lockrwl.readLock().lock();//6. 上读锁}finally{ rwl.writeLock().unlock();// Unlock write, still hold read //7. 解除写锁} }try{ use(data); }finally{ rwl.readLock().unlock();//8. 解除读锁} } }
比如现在有线程ABCDE五个线程,使用processCachedData()方法,接下来会发现如下步骤。
-> DE线程滞后,ABC同时进入到步骤1. 上读锁
-> ABC进入到步骤2. 验证cacheValid。(新实例中cacheValid初始为fasle,所以进入if条件句中)
-> ABC执行步骤3. 解除读锁。
-> 假设此时A率先完成步骤4. 上写锁。
-> BC无法获取写锁,处于等待状态,被阻塞在步骤4。 上写锁。此时D线程执行使用processCachedData()方法,被阻塞在步骤1. 上读锁。
-> A进入到步骤5. 验证cacheValid。
步骤五很关键,如果线程A写完后,解除了写锁,此时新的线程E获取到了写锁,就会写入新数据,此时就不是同步锁了,程序出错。
-> A修改数据,cacheValid置为true。步骤6和步骤7是写锁的降级操作,即写锁释放的时候,先降级为读锁,这样其他等待获取写锁的线程会继续等待,然后再释放写锁,保证同步性。
-> A执行完步骤8,BC阻塞结束,其中一位获取写锁。
如果你在学习Java的过程中或者在工作中遇到什么问题都可以来群里提问,阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!可以加群找我要课堂链接 注意:是免费的 没有开发经验误入哦! 非喜勿入! 学习交流QQ群:478052716
JAVA读锁不使用效果一样_Java使用读写锁替代同步锁相关推荐
- Java多线程学习十七:读锁应该插队吗?什么是读写锁的升降级?
读锁应该插队吗?以及什么是读写锁的升降级. 读锁插队策略 首先,我们来看一下读锁的插队策略,公平与非公平锁中讲到的 ReentrantLock,如果锁被设置为非公平,那么它是可以在前面线程释放锁的瞬间 ...
- 【JAVA SE】第十六章 进程、线程、同步锁和线程锁的简介
第十六章 进程.线程.同步锁和线程安全问题 文章目录 第十六章 进程.线程.同步锁和线程安全问题 一.进程 1.基本介绍 2.进程模型 二.线程 1.基本介绍 2.线程的生命周期 3.线程的优先级 4 ...
- Java多线程学习十六:读写锁 ReadWriteLock 获取锁有哪些规则
读写锁 ReadWriteLock 获取锁有哪些规则呢? 在没有读写锁之前,我们假设使用普通的 ReentrantLock,那么虽然我们保证了线程安全,但是也浪费了一定的资源,因为如果多个读操作同时进 ...
- java读写锁降级_java的读写锁中锁降级的问题
读写锁是什么我就不多说了,下面说什么是锁降级 锁降级: 锁降级指的是写锁降级成为读锁.如果当前线程拥有写锁,然后将其释放,最后再获取读锁,这种分段完成的过程不能称之为锁降级.锁降级是指把持住(当前拥有 ...
- Java高并发编程(七):读写锁、LockSupport、Condition
读写锁定义:读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读 线程和其他写线程均被阻塞.读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很 ...
- java 单例 读写锁_终极锁实战:单JVM锁+分布式锁
目录 1.前言 2.单JVM锁 3.分布式锁 4.总结 =========正文分割线================= 1.前言 锁就像一把钥匙,需要加锁的代码就像一个房间.出现互斥操作的典型场景:多 ...
- java dom4j读写锁,java锁的深度化-重入锁,读写锁,乐观锁,悲观锁
1.重入锁 目的:避免死锁的现象 锁作为并发共享数据,保证一致性的工具,在java平台有多种实现synchronized(重量级)和ReentrantLock(轻量级)等等,这些已经写好提供的锁为我们 ...
- Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除
文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...
- 谈谈java并发锁(重入锁、读写锁、公平锁)
目录 重入锁 简单重入锁 重入锁的等待通知(Condition) 多Condition 公平锁和非公平锁 读写锁ReentrantReadWriteLock 锁优化总结: 重入锁和读写锁,他们具有比s ...
最新文章
- Android 系统提供的文件下载
- Chrome 调试 Android WebView 网页
- Python的位置参数、默认参数、关键字参数、可变参数之间的区别
- 区块链演进及跨域安全解决方案
- AnkhSVN使用手册
- Poj1218_THE DRUNK JAILER(水题)
- 高程(三)笔记---- 第三章
- igmp是哪个层协议_通俗易懂网络协议(IP)
- fluent并行 linux_windows 系统下启动linux主机群的fluent并行操作.docx
- FPGA学习笔记---用Quartus II生成输入输出框图
- Python 5 运算符
- 见过的最详强的讲ESP定律脱壳(推荐)
- 很好的c++和Python混合编程文章
- android qq群加群代码,QQ群一键强制加群API源代码
- 2022李宏毅机器学习hw2
- Laravel框架简介与环境搭建
- Android Studio连接MySQL:问题解决:虚拟机无法连接本地SQL,coon总为空
- 高中数学关于计算机的知识,高中数学必修三-算法概念基础知识解读
- 测试公开课资料系列02--Postman之chai.js断言应用
- 人工智能革命,是创造就业还是摧毁就业?
热门文章
- 解决这个警告⚠️:warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory...
- 线性映射和线性变换的区别
- MVC教程第六篇:拦截器
- NHibernate笔记Ⅲ--关于EF和NH的比较
- 漫步数理统计二十八——混合分布
- pytorch中获取指定位置元素
- ubuntu下kaldi的安装以及实例的运行
- win7安装TensorFlow-gpu 2.3详细教程(CUDA10.1,cuDNN7)
- 循环序列模型 —— 1.7 对新序列采样
- TensorFlow 第二步 小试牛刀:一个神经元