应用情景

前一阵有个做反抄袭检测的小伙伴问了我一个问题。

---

在多线程里就是有个变量,我需要读取它来判断是否给它写入一些信息。

打算加锁,但是如果读取时候加入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使用读写锁替代同步锁相关推荐

  1. Java多线程学习十七:读锁应该插队吗?什么是读写锁的升降级?

    读锁应该插队吗?以及什么是读写锁的升降级. 读锁插队策略 首先,我们来看一下读锁的插队策略,公平与非公平锁中讲到的 ReentrantLock,如果锁被设置为非公平,那么它是可以在前面线程释放锁的瞬间 ...

  2. 【JAVA SE】第十六章 进程、线程、同步锁和线程锁的简介

    第十六章 进程.线程.同步锁和线程安全问题 文章目录 第十六章 进程.线程.同步锁和线程安全问题 一.进程 1.基本介绍 2.进程模型 二.线程 1.基本介绍 2.线程的生命周期 3.线程的优先级 4 ...

  3. Java多线程学习十六:读写锁 ReadWriteLock 获取锁有哪些规则

    读写锁 ReadWriteLock 获取锁有哪些规则呢? 在没有读写锁之前,我们假设使用普通的 ReentrantLock,那么虽然我们保证了线程安全,但是也浪费了一定的资源,因为如果多个读操作同时进 ...

  4. java读写锁降级_java的读写锁中锁降级的问题

    读写锁是什么我就不多说了,下面说什么是锁降级 锁降级: 锁降级指的是写锁降级成为读锁.如果当前线程拥有写锁,然后将其释放,最后再获取读锁,这种分段完成的过程不能称之为锁降级.锁降级是指把持住(当前拥有 ...

  5. Java高并发编程(七):读写锁、LockSupport、Condition

    读写锁定义:读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读 线程和其他写线程均被阻塞.读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很 ...

  6. java 单例 读写锁_终极锁实战:单JVM锁+分布式锁

    目录 1.前言 2.单JVM锁 3.分布式锁 4.总结 =========正文分割线================= 1.前言 锁就像一把钥匙,需要加锁的代码就像一个房间.出现互斥操作的典型场景:多 ...

  7. java dom4j读写锁,java锁的深度化-重入锁,读写锁,乐观锁,悲观锁

    1.重入锁 目的:避免死锁的现象 锁作为并发共享数据,保证一致性的工具,在java平台有多种实现synchronized(重量级)和ReentrantLock(轻量级)等等,这些已经写好提供的锁为我们 ...

  8. Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除

    文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...

  9. 谈谈java并发锁(重入锁、读写锁、公平锁)

    目录 重入锁 简单重入锁 重入锁的等待通知(Condition) 多Condition 公平锁和非公平锁 读写锁ReentrantReadWriteLock 锁优化总结: 重入锁和读写锁,他们具有比s ...

最新文章

  1. Android 系统提供的文件下载
  2. Chrome 调试 Android WebView 网页
  3. Python的位置参数、默认参数、关键字参数、可变参数之间的区别
  4. 区块链演进及跨域安全解决方案
  5. AnkhSVN使用手册
  6. Poj1218_THE DRUNK JAILER(水题)
  7. 高程(三)笔记---- 第三章
  8. igmp是哪个层协议_通俗易懂网络协议(IP)
  9. fluent并行 linux_windows 系统下启动linux主机群的fluent并行操作.docx
  10. FPGA学习笔记---用Quartus II生成输入输出框图
  11. Python 5 运算符
  12. 见过的最详强的讲ESP定律脱壳(推荐)
  13. 很好的c++和Python混合编程文章
  14. android qq群加群代码,QQ群一键强制加群API源代码
  15. 2022李宏毅机器学习hw2
  16. Laravel框架简介与环境搭建
  17. Android Studio连接MySQL:问题解决:虚拟机无法连接本地SQL,coon总为空
  18. 高中数学关于计算机的知识,高中数学必修三-算法概念基础知识解读
  19. 测试公开课资料系列02--Postman之chai.js断言应用
  20. 人工智能革命,是创造就业还是摧毁就业?

热门文章

  1. 解决这个警告⚠️:warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory...
  2. 线性映射和线性变换的区别
  3. MVC教程第六篇:拦截器
  4. NHibernate笔记Ⅲ--关于EF和NH的比较
  5. 漫步数理统计二十八——混合分布
  6. pytorch中获取指定位置元素
  7. ubuntu下kaldi的安装以及实例的运行
  8. win7安装TensorFlow-gpu 2.3详细教程(CUDA10.1,cuDNN7)
  9. 循环序列模型 —— 1.7 对新序列采样
  10. TensorFlow 第二步 小试牛刀:一个神经元