ReentrantReadWriteLock读写锁的使用
Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。
读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!
ReentrantReadWriteLock会使用两把锁来解决问题,一个读锁,一个写锁
线程进入读锁的前提条件:
没有其他线程的写锁,
没有写请求或者有写请求,但调用线程和持有锁的线程是同一个
线程进入写锁的前提条件:
没有其他线程的读锁
没有其他线程的写锁
到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限。它和后者都是单独的实现,彼此之间没有继承或实现的关系。然后就是总结这个锁机制的特性了:
(a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想。
(b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有。反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(a),呵呵.
(c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥。这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量。
(d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。
(e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出UnsupportedOperationException异常。
下面看一个读写锁的例子:
1 package com.thread;2 3 import java.util.Random;4 import java.util.concurrent.locks.ReentrantReadWriteLock;5 6 public class ReadWriteLockTest {7 public static void main(String[] args) {8 final Queue3 q3 = new Queue3();9 for(int i=0;i<3;i++) 10 { 11 new Thread(){ 12 public void run(){ 13 while(true){ 14 q3.get(); 15 } 16 } 17 18 }.start(); 19 } 20 for(int i=0;i<3;i++) 21 { 22 new Thread(){ 23 public void run(){ 24 while(true){ 25 q3.put(new Random().nextInt(10000)); 26 } 27 } 28 29 }.start(); 30 }31 } 32 } 33 34 class Queue3{ 35 private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。 36 private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 37 public void get(){ 38 rwl.readLock().lock();//上读锁,其他线程只能读不能写 39 System.out.println(Thread.currentThread().getName() + " be ready to read data!"); 40 try { 41 Thread.sleep((long)(Math.random()*1000)); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 System.out.println(Thread.currentThread().getName() + "have read data :" + data); 46 rwl.readLock().unlock(); //释放读锁,最好放在finnaly里面 47 } 48 49 public void put(Object data){ 50 51 rwl.writeLock().lock();//上写锁,不允许其他线程读也不允许写 52 System.out.println(Thread.currentThread().getName() + " be ready to write data!"); 53 try { 54 Thread.sleep((long)(Math.random()*1000)); 55 } catch (InterruptedException e) { 56 e.printStackTrace(); 57 } 58 this.data = data; 59 System.out.println(Thread.currentThread().getName() + " have write data: " + data); 60 61 rwl.writeLock().unlock();//释放写锁 62 } 63 }
Thread-0 be ready to read data! Thread-1 be ready to read data! Thread-2 be ready to read data! Thread-0have read data :null Thread-2have read data :null Thread-1have read data :null Thread-5 be ready to write data! Thread-5 have write data: 6934 Thread-5 be ready to write data! Thread-5 have write data: 8987 Thread-5 be ready to write data! Thread-5 have write data: 8496
下面使用读写锁模拟一个缓存器:
1 package com.thread;2 3 import java.util.HashMap;4 import java.util.Map;5 import java.util.concurrent.locks.ReadWriteLock;6 import java.util.concurrent.locks.ReentrantReadWriteLock;7 8 public class CacheDemo {9 private Map<String, Object> map = new HashMap<String, Object>();//缓存器 10 private ReadWriteLock rwl = new ReentrantReadWriteLock(); 11 public static void main(String[] args) { 12 13 } 14 public Object get(String id){ 15 Object value = null; 16 rwl.readLock().lock();//首先开启读锁,从缓存中去取 17 try{ 18 value = map.get(id); 19 if(value == null){ //如果缓存中没有释放读锁,上写锁 20 rwl.readLock().unlock(); 21 rwl.writeLock().lock(); 22 try{ 23 if(value == null){ 24 value = "aaa"; //此时可以去数据库中查找,这里简单的模拟一下 25 } 26 }finally{ 27 rwl.writeLock().unlock(); //释放写锁 28 } 29 rwl.readLock().lock(); //然后再上读锁 30 } 31 }finally{ 32 rwl.readLock().unlock(); //最后释放读锁 33 } 34 return value; 35 } 36 37 }
转载于:https://www.cnblogs.com/barrywxx/p/8426758.html
ReentrantReadWriteLock读写锁的使用相关推荐
- ReentrantReadWriteLock读写锁及其在 RxCache 中的使用
一. ReentrantReadWriteLock读写锁 Lock 是相当于 synchronized 更面向对象的同步方式,ReentrantLock 是 Lock 的实现. 本文要介绍的 Reen ...
- 浅析ReentrantReadWriteLock读写锁
在并发场景中用于解决线程安全的问题,我们会高频率的使用到独占式锁,通常使用java提供的关键字synchronized或者concurrents包中实现了Lock接口ReentrantLock.它们都 ...
- ReentrantReadWriteLock读写锁(读多写少场景)
ReentrantReadWriteLock读写锁 适合读多写少的场景. 读锁ReentrantReadWriteLock.ReadLock可以被多个线程同时持有, 所以并发能力很高. 写锁Reent ...
- android读写锁,ReentrantReadWriteLock读写锁及其在 RxCache 中的使用
一. ReentrantReadWriteLock读写锁 Lock 是相当于 synchronized 更面向对象的同步方式,ReentrantLock 是 Lock 的实现. 本文要介绍的 Reen ...
- ReentrantReadWriteLock(读写锁)
为了提高性能,java提供了读写锁, 读锁: 在读的地方使用读锁,可以多个线程同时读. 写锁: 在写的地方使用写锁,只要有一个线程在写,其他线程就必须等待 例子: public static Read ...
- ReentrantReadWriteLock读写锁
关注微信公众号JavaStorm获取最新文章. JavaStorm 概述 ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他 ...
- 并发锁之二:ReentrantReadWriteLock读写锁
一.简介 读写锁是一种特殊的自旋锁,它把对共享资源对访问者划分成了读者和写者,读者只对共享资源进行访问,写者则是对共享资源进行写操作.读写锁在ReentrantLock上进行了拓展使得该锁更适合读操作 ...
- java并发-ReentrantReadWriteLock读写锁
一.概念 Java常见的多是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞.读写锁维护了一对锁,一个读锁 ...
- ReentrantReadWriteLock——读写锁如何升级,为何读写锁不能插队?
我们主要探讨读锁应该插队吗?以及什么是读写锁的升降级. 读锁插队策略: 首先,我们来看一下读锁的插队策略,在这里先快速回顾一下在 24 课时公平与非公平锁中讲到的 ReentrantLock, ...
最新文章
- Python:读取两种Word文件简述及文件未能引发事件错误
- 信鸽 ios tag推送 php,iOS 关于信鸽推送点击推送通知的处理
- AVAudioPlayer音频播放器-备用
- 包含min函数的栈 大坑
- 【pointnet++点云识别】基于pointnet++的点云地理数据识别的MATLAB仿真
- git reset revert 回退回滚取消提交返回上一版本
- 【Qt5.8】TypeError: Property 'asciify' of object Core问题解决办法
- centos7 配置虚拟交换机(物理交换机truckport设置)(使用brctl)
- Python之分组级运算——【transform()方法、apply()方法】
- Tensorflow Serving Docker compose 部署服务细节(Ubuntu)
- fedora下编译运行java傻瓜入门级教程
- 专科python应届生工资多少-请问学过一点python,应届生怎么找工作?
- Google IO 2015 Material Now
- 【预测模型】基于matlab GUI BP神经网络预测【含Matlab源码 934期】
- 均衡发展学校计算机室解说词,迎接省均衡发展学校解说词
- 苹果偷学微信代码,程序员小哥:天知道微信为什么会引用这个变量
- 诺瓦-测试-面经(一面+二面)
- 使用excelJs.js,导出excel,可以设置序列以及下拉框的联动
- unity 官方案例之刚体控制人物移动
- 如何为自己制作出一份优秀的简历