java中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异常。
下面看一个读写锁的例子:
- package com.thread;
- import java.util.Random;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- public class ReadWriteLockTest {
- public static void main(String[] args) {
- final Queue3 q3 = new Queue3();
- for(int i=0;i<3;i++)
- {
- new Thread(){
- public void run(){
- while(true){
- q3.get();
- }
- }
- }.start();
- }
- for(int i=0;i<3;i++)
- {
- new Thread(){
- public void run(){
- while(true){
- q3.put(new Random().nextInt(10000));
- }
- }
- }.start();
- }
- }
- }
- class Queue3{
- private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
- private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- public void get(){
- rwl.readLock().lock();//上读锁,其他线程只能读不能写
- System.out.println(Thread.currentThread().getName() + " be ready to read data!");
- try {
- Thread.sleep((long)(Math.random()*1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "have read data :" + data);
- rwl.readLock().unlock(); //释放读锁,最好放在finnaly里面
- }
- public void put(Object data){
- rwl.writeLock().lock();//上写锁,不允许其他线程读也不允许写
- System.out.println(Thread.currentThread().getName() + " be ready to write data!");
- try {
- Thread.sleep((long)(Math.random()*1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- this.data = data;
- System.out.println(Thread.currentThread().getName() + " have write data: " + data);
- rwl.writeLock().unlock();//释放写锁
- }
- }
- 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
下面使用读写锁模拟一个缓存器:
- package com.thread;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.locks.ReadWriteLock;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- public class CacheDemo {
- private Map<String, Object> map = new HashMap<String, Object>();//缓存器
- private ReadWriteLock rwl = new ReentrantReadWriteLock();
- public static void main(String[] args) {
- }
- public Object get(String id){
- Object value = null;
- rwl.readLock().lock();//首先开启读锁,从缓存中去取
- try{
- value = map.get(id);
- if(value == null){ //如果缓存中没有释放读锁,上写锁
- rwl.readLock().unlock();
- rwl.writeLock().lock();
- try{
- if(value == null){
- value = "aaa"; //此时可以去数据库中查找,这里简单的模拟一下
- }
- }finally{
- rwl.writeLock().unlock(); //释放写锁
- }
- rwl.readLock().lock(); //然后再上读锁
- }
- }finally{
- rwl.readLock().unlock(); //最后释放读锁
- }
- return value;
- }
- }
java中ReentrantReadWriteLock读写锁的使用的更多相关文章
- java多线程:并发包中ReentrantReadWriteLock读写锁的锁降级模板
写锁降级为读锁,但读锁不可升级或降级为写锁. 锁降级是为了让当前线程感知到数据的变化. //读写锁 private ReentrantReadWriteLock lock=new ReentrantR ...
- java多线程:并发包中ReentrantReadWriteLock读写锁的原理
一:读写锁解决的场景问题--->数据的读取频率远远大于写的频率的场景,就可以使用读写锁.二:读写锁的结构--->用state一个变量.将其转化成二进制,前16位为高位,标记读线程获取锁的次 ...
- Java中的读写锁
一.读写锁 1.初识读写锁 a)Java中的锁——Lock和synchronized中介绍的ReentrantLock和synchronized基本上都是排它锁,意味着这些锁在同一时刻只允许一个线程进 ...
- java中的读/写锁
读写锁接口:ReadWriteLock,它的具体实现类为:ReentrantReadWriteLock 使用场景: 对于一个资源,读读能共存,读写不能共存,写写不能共存. 锁降级:从写锁变成读锁: 锁 ...
- 22、Java并发性和多线程-Java中的读/写锁
以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...
- Java并发包源码学习系列:ReentrantReadWriteLock读写锁解析
目录 ReadWriteLock读写锁概述 读写锁案例 ReentrantReadWriteLock架构总览 Sync重要字段及内部类表示 写锁的获取 void lock() boolean writ ...
- ReentrantReadWriteLock读写锁详解
一.读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁.在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源:但是如果一个线 ...
- ReentrantReadWriteLock读写锁的使用
Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...
- ReentrantReadWriteLock读写锁的使用2
本文可作为传智播客<张孝祥-Java多线程与并发库高级应用>的学习笔记. 这一节我们做一个缓存系统. 在读本节前 请先阅读 ReentrantReadWriteLock读写锁的使用1 第一 ...
随机推荐
- Java基础知识强化之集合框架笔记75:哈希表
1. 哈希表数据结构(数组): 2. 哈希表确定元素是否相同: (1)判断的是两个元素的哈希值是否相同 如果相同,再判断两个对象内容是否相同 (2)判断哈希值相 ...
- javascript编程的最佳实践推荐
推荐的javascript编程的最佳实践,摘要记录在这里: 可维护的代码保证代码的性能部署代码 1 可维护的代码1.1什么是维护的代码:可理解性——其他人可以接手代码并理解它的意图和一般途径,而无需原 ...
- oracle 10g升级到11g
Linux 上Oracle RAC 10g 升级到 Oracle RAC 11g 了解如何在 Oracle Enterprise Linux 5 上逐步将 Oracle RAC 10g 第 2 版升级 ...
- linux安装gcc的一些问题。
输入命令:yum install gcc 提示: Loaded plugins: fastestmirror, langpacksExisting lock /var/run/yum.pid: ano ...
- js实现归并排序
function merge(s_arr, d_arr, start, middle, end){ var s_temp = start; var m_temp = middle+1; var tem ...
- poj 2411 状态压缩dp
思路:将每一行看做一个二进制位,那么所有的合法状态为相邻为1的个数一定要为偶数个.这样就可以先把所有的合法状态找到.由于没一层的合法状态都是一样的,那么可以用一个数组保存.由第i-1行到第i行的状态转 ...
- Mirco2440核心板设计思考
1.核心板架构 注意的是:此处的RAM和ROM都是外置的 硬件框架 S3C2440+ SDRAM + NAND Flash + NOR Flash 也就是 CPU + RAM + ROM 2.S3C2 ...
- Nginx - HTTP Configuration, Module Directives
Socket and Host Configuration This set of directives will allow you to configure your virtual hosts. ...
- Android 中的图像特效(Matrix)
以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,现在在Android中有一个Matrix类,它的中文意思就是矩阵.Matrix主要是用于图像的缩放.平移.旋转.扭曲等操作.图像处理,主要用到的 ...
- money 转换成 varchar
Sql :cast(sum(colname) as varchar) 或者 convert(varchar,sum(colname)) ),sum(colname))