Java多线程并发之读写锁

本文主要内容:读写锁的理论;通过生活中例子来理解读写锁;读写锁的代码演示;读写锁总结。通过理论(总结)-例子-代码-然后再次总结,这四个步骤来让大家对读写锁的深刻理解。

本篇是《凯哥(凯哥Java:kagejava)并发编程学习》系列之《Lock系列》教程的第七篇:《Java并发包下锁学习第七篇:读写锁》。

一:读写锁的理论

什么是读写锁?

多个线程同时读一个资源类是没有任何问题的,所以为了满足在并发的情况下,读取共享资源应该是可以同时进行的;但是,如果一个线程想要去写共享资源,就不应该再有其他线程可以对该共享资源进行读或者是写操作了。

即读写锁在同一时刻可以允许多个多线程访问,但是在写线程访问的时候,所有的读线程和其他写线程都会被阻塞。读写锁实际维护了一对锁,一个读锁,一个写锁,通过分离读锁和写锁,使得其并发性比独占式锁(排他锁)有了很大的提升。

为什么需要读写锁?

通过前面文章的学习,我们知道了ReentrantLock(下文简称:RLock)对象了。Rlock比起synchronized(下文简称Sync)来说有三个优点:RLock可以被中断;RLock可以有公平锁;RLock可以绑定多个条件。那么既然RLock比Sync有这么多优点,为什么还需要读写锁呢?

那是因为RLock是独占式(排他) 锁,即当线程1获取到资源的时候,其他线程不能再来操作共享资源了。就算是RLock的操作是读取的时候,其他线程也不能读取共享资源的操作。这在现实生活中是不符合逻辑的(在下文神话中读写锁的例子中我们就能体会到为什么不符合逻辑的),而且性能也比较慢。所以就有了读写锁的出现。

二:读写锁的理解

生活中读写锁的例子

例子一:我们大家去火车站乘车的时候,有个大大的公示屏幕,会告诉大家当前车次是否晚点。显示屏是给给所有乘客看的,如果火车晚点,对应车次后面就会被修改成晚点大约xxx分钟。这个修改的动作只能是火车站内部人员来操作的,我们乘客是不能操作的。这个过程,站在并发角度来分析的的话:电子屏幕是共享数据;千千万万的乘客是不同的线程;火车站内部工作人员也是不同的线程;乘客是读资源的线程,当一个线程来读取的时候,其他线程也可以读取操作的;火车站内部工作人员修改火车信息的时候,同时只能有一个工作人员来修改,不能两个都来修改。如果两个都来修改的话,上一秒显示晚点1min,下一秒显示正常。这个是不行的,乘客有可能会错过乘车的。所以修改的时候同时只能由一个工作人员来修改。

例子二:我们在玩王者荣耀的时候,有时候会遇到停服更新的。在不更新前,所有玩家都可以玩,当停服更新的时候,所有玩家就不能玩了。这个操作在并发角度来说:千千万万的玩家是读共享资源的;游戏维护者是写操作的。当停服更新的时候,读操作就被阻塞了,只能等写操作,也就是更新完成后,才可以接着玩。

通过上面两个例子我们可以分析到读写锁的三个参与者:共享资源;读对象;写对象。而且读和写一般是分离的。

三:读写锁的代码演示

我们就用火车站进站案例来模拟:

未使用锁的时候

先来看看屏幕对象:

再来看看多个工作人员更新操作及多个乘客获取操作:

查看运行结果:

从运行结果中,我们可以发现当工号未13的还没有更新完车次信息的时候,工号12和14的员工也来更新了。这种操作是不允许的。因为写操作要原子性,要独占。当工作人员甲在修改的时候车次信息的时候,其他工作人员不能同时修改同一个车次信息了。而且从乘客获取车次信息的数据来看,获取到的只是工号是13的。这个时候获取到的数据不一定是正确的了。所以,不使用锁是不行的。

使用排他锁

如果使用独占式做的话,我们查看运行结果:

从运行结果来看,再读取的时候,需要一个一个读取的。当16号乘客查看的时候,17号乘客是不能查看的。这个是不符合实际业务逻辑的。所以,独占式(排他锁)RLock在这里不适合。我们再来看看读写锁:

使用读写锁

先来看看使用读写锁的屏幕对象

再来看看运行结果:

从运行结果中,我们可以看到,工作人员是一个一个的操作完成的。当14号操作完成之后,13号和12号才可以操作的。这个符号我们正常的业务。乘客读取的时候,读取到的都是最后一次更新,这个也符合我们的业务。所以,通过读写锁来操作车站屏幕是可以的。

四:读写锁总结

4.1:wrLock类对象

同样包含了公平锁和非公平锁。

其中ReadLock是读锁对象;WriteLock是写锁对象。

4.2:使用语法

读操作使用ReadLock

编辑

写操作的时候,使用WriteLock对象:

4.3:总结

读写锁(ReentrantReadWriteLock),凯哥就简写rwLock。也可以实现公平和非公平的。其内部维护了一对锁:一个读锁(ReadLock对象),一个写锁(writeLock对象),通过读写分离的方式来提高并发性能。读写锁也叫共享锁。其共享是在读数据的时候,可以让多个线程同时进行读操作的。在写的时候具有排他性,其他读或者写操作都要被阻塞。

一般情况下,读写锁的性能都会比排他锁性能好,那是因为,大多数场景读操作多于写操作的。在读多与写的场景下,读写锁能够提供比排他锁更好的并性能和吞吐量。

​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​欢迎来聊~

原文出处:https://www.cnblogs.com/kaigejava/p/12651268.html

java写车次查询_从火车站车次公示栏来学Java读写锁相关推荐

  1. java车次信息_从火车站车次公示栏来学Java读写锁

    Java多线程并发之读写锁 本文主要内容:读写锁的理论:通过生活中例子来理解读写锁:读写锁的代码演示:读写锁总结.通过理论(总结)-例子-代码-然后再次总结,这四个步骤来让大家对读写锁的深刻理解. 本 ...

  2. java写便签_如何编写一个便签程序(用Java语言编写)

    如何编写一个便签程序(用Java语言编写) 热度:336   发布时间:2011-02-18 11:44:16 如何编写一个便签程序(用Java语言编写) 因为以前没有好好学习Java,都搞忘了,请大 ...

  3. 用java写一个日历_使用JAVA写一个简单的日历

    JAVA写一个简单的日历 import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDa ...

  4. java中override快捷键_【基础回溯1】面试又被 Java 基础难住了?推荐你看看这篇文章。...

    本文已经收录自 https://github.com/Snailclimb/JavaGuide  (59k+ Star):[Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识. ...

  5. Java并发编程实战_不愧是领军人物!这种等级的“Java并发编程宝典”谁能撰写?...

    前言 大家都知道并发编程技术就是在同一个处理器上同时的去处理多个任务,充分的利用到处理器的每个核心,最大化的发挥处理器的峰值性能,这样就可以避免我们因为性能而产生的一些问题. 大厂的核心负载肯定是非常 ...

  6. 用java写个记账本,融会贯通你的J2SE(一)java实战项目 Java项目

    用java写个记账本,融会贯通你的J2SE(一) 项目源码,点击这里,注册获取 获取更多java学习资料 学习了这么多J2SE基础和中级的知识点,接下来就需要一个综合性的项目把这些的知识点都融会贯通. ...

  7. Java实现一元函数遗传算法_遗传算法的基本概念和实现,附Java实现案例!

    基因遗传算法是一种灵感源于达尔文自然进化理论的启发式搜索算法.该算法反映了自然选择的过程,即最适者被选定繁殖,并产生下一代.本文简要地介绍了遗传算法的基本概念和实现,希望能为读者展示启发式搜索的魅力. ...

  8. 在Java中编写实现_在运行时编写和实现新的Java类文件

    是否可以通过某种方式将新的Java类"导入"到正在运行的程序中并加以利用? 我可以让一个程序创建一个类型为'.java'的新文件,然后将其包含在项目文件中并引用它,而不必重新启动该 ...

  9. java 安卓客户端开发_《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端...

    1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...

最新文章

  1. 使用c3p0对mysql进行增删改查_c3p0连接池连接数据库 并增删改查
  2. 通用异步 Windows Socket TCP 客户端组件的设计与实现
  3. Java 8 - 02 Lambda Expression
  4. 大话移动通信pdf_移动通信是怎么实现的?
  5. 基于CNN的性别、年龄识别及Demo实现
  6. 怎么解决eclipse报PermGen space异常的问题
  7. No services have been found解决方案
  8. 给窗口设置系统级或窗口级的热键
  9. codevs 4927 线段树练习5 线段树基本操作模板
  10. Docker-删除untagged docker images
  11. Creo6.0无人机建模与结构设计视频教程
  12. 查看oracle磁盘组空间,shell脚本检查oracle中的ASM磁盘组空间并发送邮件
  13. XP纯净版光盘ISO镜像文件
  14. ZZNU2141: 2333
  15. 项目无法启动,Disconnected from the target VM
  16. 朋友圈gys是什么意思,女生微信朋友圈说说经典句子
  17. 数据可视化8_数据分析的一般流程
  18. 微信开发者工具调试公众号网页提示: 未绑定为公众号的网页开发者
  19. 前端开发:Vue组件中的冒号用法
  20. Py西游攻关之基础数据类型

热门文章

  1. UVM:6.3.2 uvm_create 与 uvm_send
  2. [百度开放云骑士之夜]Be a knight at the night
  3. 【数学】1.分布函数与概率密度函数
  4. demo对接php,喜马拉雅数据API 接入 demo PHP版 API
  5. HTTP协议详解 - 通过C++实现HTTP服务剖析HTTP协议
  6. react错误:Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infini
  7. 1.5-14:人口增长问题
  8. 刘擎《西方现代思想讲义》思维导图xmind及笔记
  9. 基于相移法的结构光三维测量技术
  10. python 鱼骨图_python面向对象编程,鱼骨图分析法