ReadWriteLock也是一个接口,提供了readLock和writeLock两种锁的操作机制,一个资源可以被多个线程同时读,或者被一个线程写,但是不能同时存在读和写线程。

使用场合

假设在程序中定义一个共享的数据结构用作缓存,它大部分时间提供读服务(例如:查询和搜索),而写操作占有的时间很少,但是写操作完成之后的更新需要对后续的读服务可见。

在没有读写锁支持的(Java 5 之前)时候,如果需要完成上述工作就要使用Java的等待通知机制,就是当写操作开始时,所有晚于写操作的读操作均会进入等待状态,只有写操作完成并进行 通知之后,所有等待的读操作才能继续执行(写操作之间依靠synchronized关键字进行同步),这样做的目的是使读操作都能读取到正确的数据,而不会出现脏读。改用读写锁实现上述功能,只需要在读操作时获取读锁,而写操作时获取写锁即可,当写锁被获取到时,后续(非当前写操作线程)的读写操作都会被 阻塞,写锁释放之后,所有操作继续执行,编程方式相对于使用等待通知机制的实现方式而言,变得简单明了。

特性

ReentrantReadWriteLock的实现里面有以下几个特性

**1、公平性:非公平锁(默认)。**读线程之间没有锁操作,所以读操作没有公平性和非公平性。写操作时,由于写操作可能立即获取到锁,所以会推迟一个或多个读操作或者写操作。非公平锁的吞吐量要高于公平锁。(公平锁概念:公平锁利用AQS的CLH队列,释放当前保持的锁时,优先为等待时间最长的那个写操作分配写入锁)
**2、重入性:**读写锁允许读线程和写线程按照请求锁的顺序重新获取读取锁或者写入锁。只有写线程释放了锁,读线程才可以获取重入锁,写线程获取写入锁后可以再次获取读取锁,但是读线程获取读取锁后却不能获取写入锁。
**3、锁降级:**写线程获取写入锁后可以获取读取锁,然后释放写入锁,这样就从写入锁变成了读取锁,从而实现锁降级特性,经典cache案例使用了锁降级
**4、锁升级:**读取锁是不能直接升级为写入锁的。因此获取一个写入锁需要先释放所有的读取锁,如果有两个读取锁试图获取写入锁,且都不释放读取锁时,就会发生死锁
**5、锁获取中断:**读取锁和写入锁都支持获取锁期间被中断
**6、条件变量:**写入锁提供了条件变量的支持,但是读取锁却不允许获取条件变量,否则会得到一个UnsupportedOperationExcetpion异常
**7、重入锁:**读取锁和写入锁的数量最大分别只能是65535

读写锁机制

读-读不互斥

读-写互斥

写-写互斥

示例代码:

import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockTest {private double data = 0;ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();public void get(){try {rwl.readLock().lock();System.out.println("----Thread:"+Thread.currentThread().getName()+"----read first value:"+data);Thread.sleep(1000);System.out.println("----Thread:"+Thread.currentThread().getName()+"----read second value:"+data);rwl.readLock().unlock();} catch (Exception e) {// TODO: handle exception}}public void put(){try {rwl.writeLock().lock();data = Math.random();System.out.println("----Thread:"+Thread.currentThread().getName()+"----write first value:"+data);Thread.sleep(100);rwl.writeLock().unlock();} catch (Exception e) {// TODO: handle exception}}}
public class MainReadWritLockTest {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubfinal ReadWriteLockTest rwlt = new ReadWriteLockTest();for(int i=0; i<5;i++){new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubrwlt.get();}}).start();}for(int i=0; i<2;i++){new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubrwlt.put();}}).start();}}}

运行代码,我们可以很明显观察到,5个线程读取时,没有互斥。读完后写线程才开始执行,说明读读不互斥,读写有互斥。

运行结果:

锁升级降级示例

读写锁经典案例,防缓存系统

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockTest {ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();Map<String,Object> cache = new HashMap<String,Object>();public Object get(String key){Object value  = null;try {rwl.readLock().lock();value = cache.get(key);if(null==value){rwl.readLock().unlock();//释放都锁,获取写锁try {rwl.writeLock().lock();//获取写锁后再次判断对象是否为null,方式下一个等待的写线程进入后直接获取数据去value = cache.get(key);if(null==value){System.out.println(Thread.currentThread().getName());value="aaaaa";//实际操作代码从数据库中查询得到的对象cache.put(key, value);}//自身锁降级为都锁rwl.readLock().lock();} catch (Exception e) {// TODO: handle exception}finally{rwl.writeLock().unlock();//释放写锁}}} catch (Exception e) {// TODO: handle exception}finally{rwl.readLock().unlock();}return value;}}
import java.util.HashMap;
import java.util.Map;public class MainReadWritLockTest {Map<String,Object> cache = new HashMap<String,Object>();/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubfinal ReadWriteLockTest rwlt = new ReadWriteLockTest();for(int i=0; i<10;i++){new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubObject value= rwlt.get("id");System.out.println(Thread.currentThread().getName()+"--"+value);}}).start();}}}

上述示例中,cache组合了一个非线程安全的HashMap作为缓存的实现,同时使用读写锁的读锁和写锁来保证cache是线程安全的。在读操作 get(String key)方法中,需要获取读锁,这使得并发访问该方法时不会被阻塞。写操作put(String key, Object value)方法,在更新HashMap时必须提前获取写锁,当写锁被获取后,其他线程对于读锁和写锁的获取均被阻塞,而只有写锁被释放 之后,其他读写操作才能继续。

ReadLock和WriteLock(读写锁)相关推荐

  1. java writelock 问题_【转】java并发编程系列之ReadWriteLock读写锁的使用

    前面我们讲解了Lock的使用,下面我们来讲解一下ReadWriteLock锁的使用,顾明思义,读写锁在读的时候,上读锁,在写的时候,上写锁,这样就很巧妙的解决synchronized的一个性能问题:读 ...

  2. java锁(公平锁和非公平锁、可重入锁(又名递归锁)、自旋锁、独占锁(写)/共享锁(读)/互斥锁、读写锁)

    前言 本文对Java的一些锁的概念和实现做个整理,涉及:公平锁和非公平锁.可重入锁(又名递归锁).自旋锁.独占锁(写)/共享锁(读)/互斥锁.读写锁 公平锁和非公平锁 概念 公平锁是指多个线程按照申请 ...

  3. ReentrantReadWriteLock读写锁的使用

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

  4. ReentrantReadWriteLock(读写锁)

    为了提高性能,java提供了读写锁, 读锁: 在读的地方使用读锁,可以多个线程同时读. 写锁: 在写的地方使用写锁,只要有一个线程在写,其他线程就必须等待 例子: public static Read ...

  5. Java并发- 读写锁中的性能之王:StampedLock

    为什么StampedLock这么神奇?能够达到这种效果,它的核心思想在于,在读的时候如果发生了写,应该通过重试的方式来获取新的值,而不应该阻塞写操作.这种模式也就是典型的无锁编程思想,和CAS自旋的思 ...

  6. ReentrantReadWriteLock读写锁及其在 RxCache 中的使用

    一. ReentrantReadWriteLock读写锁 Lock 是相当于 synchronized 更面向对象的同步方式,ReentrantLock 是 Lock 的实现. 本文要介绍的 Reen ...

  7. ReentrantReadWriteLock读写锁

    关注微信公众号JavaStorm获取最新文章. JavaStorm 概述 ​ ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他 ...

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

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

  9. 死磕Java并发:J.U.C之读写锁:ReentrantReadWriteLock

    作者:chenssy 来源:http://cmsblogs.com/?p=2213 重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都 ...

最新文章

  1. 【原创】Kakfa utils源代码分析(三)
  2. python extractall函数_Pandas从str.extractall('#')中给出错误
  3. KVM配置之(3)- 克隆
  4. 嵌入式系统HAL原理与BSP的实现方法
  5. Core Data系列二——基础概念
  6. 分布式数据库TiDB是如何结合OLTP和OLAP的?
  7. canvas转盘-拯救选择困难
  8. Spring注释事务失效及解决办法
  9. C语言课后习题(35)
  10. 小程序入门学习14--用户管理
  11. 深入了解一下PYTHON中关于SOCKETSERVER的模块-A
  12. 图像处理中滤波(filtering)与卷积(convolution)的区别
  13. Atitit js canvas的图像处理类库attilax总结与事业
  14. 论文篇-----基于机器学习的交通流预测技术的研究与应用
  15. 防治计算机病毒微格教案反思,数字化微格教学实验室设备常见故障及处理方法...
  16. Idea中jclasslib的安装与使用
  17. mysql禁止明文密码_暂时在MySQL *中存储明文密码是否安全*?
  18. 每日一问 --什么是正弦信号?正弦信号有哪些特性?
  19. cad镜像后标注尺寸数字反了_CAD镜像后轴号和标注的尺寸是反的,怎么调整?
  20. 微信小程序提示:https://www.xxxxx.com 不在以下 request 合法域名列表中,请参考文档....

热门文章

  1. 用代码实现一个简单计算器
  2. 使用Nessus进行漏洞扫描
  3. pcie equalization学习笔记后续再整理
  4. 2019阿里云开年Hi购季基础云产品分会场全攻略!...
  5. 3D可视化孪生系统之燃气展示方案
  6. 全国计算机报名系统入口2020年,2020年3月全国计算机二级报名系统入口
  7. JDK8新特性相关知识讲解汇总
  8. SDP 是什么?有什么用?
  9. 多媒体系统是指利用计算机技术和什么技术,四川自考07311《多媒体技术》全真模拟试题(一)...
  10. SRS流媒体服务器SDP解析流程