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 }

转自 http://www.cnblogs.com/liuling/archive/2013/08/21/2013-8-21-03.html

ReentrantReadWriteLock读写锁的使用<转>的更多相关文章

  1. ReentrantReadWriteLock读写锁的使用

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

  2. ReentrantReadWriteLock读写锁的使用2

    本文可作为传智播客<张孝祥-Java多线程与并发库高级应用>的学习笔记. 这一节我们做一个缓存系统. 在读本节前 请先阅读 ReentrantReadWriteLock读写锁的使用1 第一 ...

  3. 锁对象-Lock: 同步问题更完美的处理方式 (ReentrantReadWriteLock读写锁的使用/源码分析)

    Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我 ...

  4. Java并发包源码学习系列:ReentrantReadWriteLock读写锁解析

    目录 ReadWriteLock读写锁概述 读写锁案例 ReentrantReadWriteLock架构总览 Sync重要字段及内部类表示 写锁的获取 void lock() boolean writ ...

  5. ReentrantReadWriteLock读写锁简单原理案例证明

    ReentrantReadWriteLock存在原因? 我们知道List的实现类ArrayList,LinkedList都是非线程安全的,Vector类通过用synchronized修饰方法保证了Li ...

  6. ReentrantReadWriteLock读写锁详解

    一.读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁.在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源:但是如果一个线 ...

  7. java多线程:并发包中ReentrantReadWriteLock读写锁的锁降级模板

    写锁降级为读锁,但读锁不可升级或降级为写锁. 锁降级是为了让当前线程感知到数据的变化. //读写锁 private ReentrantReadWriteLock lock=new ReentrantR ...

  8. java中ReentrantReadWriteLock读写锁的使用

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

  9. java多线程:ReentrantReadWriteLock读写锁使用

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

  10. ReentrantReadWriteLock读写锁的使用1

    本文可作为传智播客<张孝祥-Java多线程与并发库高级应用>的学习笔记. 一个简单的例子 两个线程,一个不断打印a,一个不断打印b public class LockTest { publ ...

随机推荐

  1. PHP的错误处理方式(开发和上线)

    对于PHP开发人员来说,一旦某个产品投入使用.应该马上将 display_errors选项关闭.以免由于这些错误所透露的路径.数据库连接.数据表等信息而遭到黑客攻击. 可是.不论什么一个产品在投入使用 ...

  2. <The Art of Readable Code> 笔记二 (上)

    第2章  封装信息到名字 (Packing information into names) 2.1  use specific words GetPage() 不如 FetchPage() 和 Dow ...

  3. Spring MVC过滤器-登录过滤

    以下代码是继承OncePerRequestFilter实现登录过滤的代码: package com.test.spring.filter; import java.io.IOException; im ...

  4. MySQL 5.1参数

    MySQL 5.1.73参数 Variable_name    Valueauto_increment_increment 1auto_increment_offset 1autocommit ONa ...

  5. 百度地图总结第二篇--POI检索功能

    简单介绍: 眼下百度地图SDK所集成的检索服务包含:POI检索.公交信息查询.线路规划.地理编码.行政区边界数据检索.在线建议查询.短串分享(包含POI搜索结果分享.驾车/公交/骑行/步行路线规划分享 ...

  6. JavaWeb 绝对路径与相对路径

      JavaWeb 绝对路径与相对路径 CreateTime--2018年4月14日16:51:19 Author:Marydon 8.1 绝对路径 web项目不可能使用绝对路径,因为: 以文件的引用 ...

  7. [MSP430]入门之中的一个 总体认识

    这是由TI公司推出的一款比較单片机, 相对stm32来说简单些, 由于它是16位的,  所以我们在学习中可能也会像51一样,  直接操纵寄存器. TI设计这款单片机的初衷是, 让它用于低功耗的嵌入式设 ...

  8. spring AOP编程--AspectJ注解方式

    1. AOP 简介 AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, ...

  9. BeanUtils的介绍使用

    BeanUtils工具 在实际的开发中我们经常需要将用户的录入的数据进行封装为对象,那么如果使用反射和内省技术就会变得吃力.因此本节主要给大家讲解一个开源的操作JavaBean的一个工具即BeanUt ...

  10. Ruby 和 Python 分析器是如何工作的?

    你好! 我作为一名编写Ruby profiler的先驱,我想对现有的Ruby和Python profiler如何工作进行一次调查. 这也有助于回答很多人的问题:“你怎么写一个profiler?” 在这 ...