独占锁:是指锁一次只能被一个线程持有,ReentrantLock和Synchronized都是独占锁。

共享锁:是指锁可以被多个线程持有。

对于ReentrantReadWriteLock,其读锁是共享锁,写锁是独占锁。

代码示例:如果不设置锁,下面这块代码执行后就会造成一段写操作在完成之前被多个其他操作打断。

  1. package com.freud.algorithm.other;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import java.util.concurrent.TimeUnit;
  6. import java.util.concurrent.locks.Lock;
  7. import java.util.concurrent.locks.ReentrantLock;
  8.  
  9. /**
  10. * 资源类
  11. */
  12. class MyCache {
  13.  
  14. private volatile Map<String, Object> map = new HashMap<>();
  15. // private Lock lock = new ReentrantLock();
  16. public void put(String key, Object value) {
  17.  
  18. System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key);
  19. // 暂停一会儿线程
  20. try {
  21. TimeUnit.MILLISECONDS.sleep(300);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. map.put(key, value);
  26. System.out.println(Thread.currentThread().getName() + "\t 写入完成");
  27. }
  28.  
  29. public void get(String key) {
  30.  
  31. System.out.println(Thread.currentThread().getName() + "\t 正在读取:");
  32. // 暂停一会儿线程
  33. try {
  34. TimeUnit.MILLISECONDS.sleep(300);
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. }
  38. Object value = map.get(key);
  39. System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + value);
  40. }
  41. }
  42.  
  43. /**
  44. * 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
  45. * 但是,如果有一个线程想去写共享资源,就不应该再有其他线程可以对这个资源进行读或者写
  46. * 小总结:
  47. * 读-读能共存
  48. * 读-写不能共存
  49. * 写-写不能共存
  50. */
  51. public class ReadWriteLockDemo {
  52.  
  53. public static void main(String[] args) {
  54.  
  55. MyCache myCache = new MyCache();
  56.  
  57. for (int i = 0; i < 5; i++) {
  58. final int tempInt = i;
  59. new Thread(() -> {
  60. myCache.put(tempInt + "", tempInt + "");
  61. }, String.valueOf(i)).start();
  62. }
  63.  
  64. for (int i = 0; i < 5; i++) {
  65. final int tempInt = i;
  66. new Thread(() -> {
  67. myCache.get(tempInt + "");
  68. }, String.valueOf(i)).start();
  69. }
  70. }
  71. }

打印:

  1. "C:\Program Files\Java\jdk1.8.0_191\bin\java" "-javaagent:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=12592:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;E:\practise\algorithm\out\production\algorithm" com.freud.algorithm.other.ReadWriteLockDemo
  2. 1 正在写入:1
  3. 0 正在写入:0
  4. 2 正在写入:2
  5. 3 正在写入:3
  6. 4 正在写入:4
  7. 0 正在读取:
  8. 1 正在读取:
  9. 2 正在读取:
  10. 3 正在读取:
  11. 4 正在读取:
  12. 1 写入完成
  13. 1 读取完成:1
  14. 0 读取完成:0
  15. 0 写入完成
  16. 2 写入完成
  17. 4 写入完成
  18. 3 写入完成
  19. 4 读取完成:null
  20. 3 读取完成:null
  21. 2 读取完成:2
  22.  
  23. Process finished with exit code 0

为了解决这个问题,使得写操作保证原子性不被其他线程打断,加了ReadWriteLock。

  1. package com.freud.algorithm.other;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import java.util.concurrent.TimeUnit;
  6. import java.util.concurrent.locks.Lock;
  7. import java.util.concurrent.locks.ReentrantLock;
  8. import java.util.concurrent.locks.ReentrantReadWriteLock;
  9.  
  10. /**
  11. * 资源类
  12. */
  13. class MyCache {
  14.  
  15. private volatile Map<String, Object> map = new HashMap<>();
  16. // 传统的Lock不足以满足需求
  17. // private Lock lock = new ReentrantLock();
  18. /**
  19. * JUC提供了ReentrantReadWriteLock
  20. */
  21. private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
  22.  
  23. /**
  24. * put方法
  25. * @param key
  26. * @param value
  27. */
  28. public void put(String key, Object value) {
  29.  
  30. rwLock.writeLock().lock();
  31. try {
  32. System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key);
  33. // 暂停一会儿线程
  34. try {
  35. TimeUnit.MILLISECONDS.sleep(300);
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39. map.put(key, value);
  40. System.out.println(Thread.currentThread().getName() + "\t 写入完成");
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. } finally {
  44. rwLock.writeLock().unlock();
  45. }
  46. }
  47.  
  48. /**
  49. * get方法
  50. * @param key
  51. */
  52. public void get(String key) {
  53.  
  54. rwLock.readLock().lock();
  55. try {
  56. System.out.println(Thread.currentThread().getName() + "\t 正在读取:");
  57. // 暂停一会儿线程
  58. try {
  59. TimeUnit.MILLISECONDS.sleep(300);
  60. } catch (InterruptedException e) {
  61. e.printStackTrace();
  62. }
  63. Object value = map.get(key);
  64. System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + value);
  65. } catch (Exception e) {
  66. e.printStackTrace();
  67. } finally {
  68. rwLock.readLock().unlock();
  69. }
  70. }
  71. }
  72.  
  73. /**
  74. * 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
  75. * 但是,如果有一个线程想去写共享资源,就不应该再有其他线程可以对这个资源进行读或者写
  76. * 小总结:
  77. * 读-读能共存
  78. * 读-写不能共存
  79. * 写-写不能共存
  80. */
  81. public class ReadWriteLockDemo {
  82.  
  83. public static void main(String[] args) {
  84.  
  85. MyCache myCache = new MyCache();
  86.  
  87. for (int i = 0; i < 5; i++) {
  88. final int tempInt = i;
  89. new Thread(() -> {
  90. myCache.put(tempInt + "", tempInt + "");
  91. }, String.valueOf(i)).start();
  92. }
  93.  
  94. for (int i = 0; i < 5; i++) {
  95. final int tempInt = i;
  96. new Thread(() -> {
  97. myCache.get(tempInt + "");
  98. }, String.valueOf(i)).start();
  99. }
  100. }
  101. }

打印:

  1. "C:\Program Files\Java\jdk1.8.0_191\bin\java" "-javaagent:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\lib\idea_rt.jar=18187:E:\Jetbrains\IntellijIDEA\IntelliJ IDEA 2017.2.6\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;E:\practise\algorithm\out\production\algorithm" com.freud.algorithm.other.ReadWriteLockDemo
  2. 0 正在写入:0
  3. 0 写入完成
  4. 1 正在写入:1
  5. 1 写入完成
  6. 2 正在写入:2
  7. 2 写入完成
  8. 3 正在写入:3
  9. 3 写入完成
  10. 4 正在写入:4
  11. 4 写入完成
  12. 1 正在读取:
  13. 0 正在读取:
  14. 3 正在读取:
  15. 4 正在读取:
  16. 2 正在读取:
  17. 2 读取完成:2
  18. 4 读取完成:4
  19. 3 读取完成:3
  20. 0 读取完成:0
  21. 1 读取完成:1
  22.  
  23. Process finished with exit code 0

Java锁_读写锁的更多相关文章

  1. 二、多线程基础-乐观锁_悲观锁_重入锁_读写锁_CAS无锁机制_自旋锁

    1.10乐观锁_悲观锁_重入锁_读写锁_CAS无锁机制_自旋锁1)乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将 比较-设置 ...

  2. 多线程编程之Apue3rd_Chapter11之互斥锁_读写锁_自旋锁

    学习了apue3rd的第11章,主要讲的是多线程编程.因为线程共享进程的资源比如堆和全局变量,多线程编程最重要的是,使用各种锁进行线程同步. 线程编程首先要学习的三个函数如下: #include &l ...

  3. JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,

    如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...

  4. Java中的锁-悲观锁、乐观锁,公平锁、非公平锁,互斥锁、读写锁

    总览图 如果文中内容有错误,欢迎指出,谢谢. 悲观锁.乐观锁 悲观锁.乐观锁使用场景是针对数据库操作来说的,是一种锁机制. 悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数 ...

  5. golang互斥锁和读写锁

    一.互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段.它由标准库代码包sync中的Mutex结构体类型代表.sync.Mutex类型(确切地说,是*sync.Mutex类型)只有两个公开 ...

  6. 从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解

    ​    同步自我的 csdn 博客 6.S081 从自旋锁.睡眠锁.读写锁到 Linux RCU 机制讲解_我说我谁呢 --CSDN博客 总结一下 O/S 课程里面和锁相关的内容. 本文是 6.S0 ...

  7. Go语言基础之13--线程安全及互斥锁和读写锁

    一.线程安全介绍 1.1 现实例子 A. 多个goroutine同时操作一个资源,这个资源又叫临界区 B. 现实生活中的十字路口,通过红路灯实现线程安全 C. 火车上的厕所(进去之后先加锁,在上厕所, ...

  8. 多线程编程_读写锁ReadWriteLock

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...

  9. PHP程序中的文件锁、互斥锁、读写锁使用技巧解析

    文件锁全名叫 advisory file lock, 书中有提及. 这类锁比较常见,例如 mysql, php-fpm 启动之后都会有一个pid文件记录了进程id,这个文件就是文件锁. 这个锁可以防止 ...

随机推荐

  1. Python-使用tkinter实现的摇骰子小游戏

    贴吧看到的一个求助题,大致需求是:3个人摇骰子,每人摇3次,点数之和最大的获胜,支持玩家名称输入.我觉得这个题目挺有意思的,做了个界面程序,欢迎大家交流指正~ #!usr/bin/env python ...

  2. Linux下C++动态加载so 调用方法

    Windows 下的C++动态加载DLL调用方法 文献参考 http://man7.org/linux/man-pages/man0/dlfcn.h.0p.html http://man7.org/l ...

  3. postcss.config.js not found

    https://github.com/ElemeFE/element/issues/10249

  4. css自动省略号...,通过css实现单行、多行文本溢出显示省略号

    网页开发过程中经常会遇到需要把多行文字溢出显示省略号,这篇文章将总结通过多种方法实现文本末尾省略号显示. 一.单行文本溢出显示省略号(…) 省略号在ie中可以使用text-overflow:ellip ...

  5. Linux上运行安卓应用:安装使用Anbox

    文章目录 #0x0 简介 #0x1 安装教程 #0x11 第一步,安装需要的内核模块 #0x12 安装Anbox #0x2 使用Anbox #0x21 一些简单的设置 #0x22 安装APK #0x3 ...

  6. 简单shellcode学习

    本文由“合天智汇”公众号首发 作者:hope 引言 之前遇到没开启NX保护的时候,都是直接用pwtools库里的shellcode一把梭,也不太懂shellcode代码具体做了些什么,遇到了几道不能一 ...

  7. java 基本语法(十九)Optional类的使用

    java.util.Optional类1.理解:为了解决java中的空指针问题而生!Optional<T> 类(java.util.Optional) 是一个容器类,它可以保存类型T的值, ...

  8. 问题:win10缺少一个或多个网络协议

    国庆回家,家里电脑连不上网了,诊断给出的结果是“缺少一个或多个网络协议” 网上这类问题提问的不少,回答的方法也是各种各样,一个一个试下来,发现这个方法是可行的. 1.打开设置--网络和Internet ...

  9. ajax配合art-template模板引擎的使用

    最近才接触js的模板引擎听说相比以前使用的js foreach加载后台返回的json数据简便很多而且效率方面也很不错.今天自己玩了一下 后台使用的是.net mvc,数据库脚本就不提供了,返回的Jso ...

  10. Burp Suite Report - 报告功能

    1. 通过点击Host选择不同的颜色,可以设置严重性: 2.生成网页版应用分析报告:选中所有条目->右击网址,保存所有选中项目,存储格式为html.