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. }

  

  1. Thread-0 be ready to read data!
  2. Thread-1 be ready to read data!
  3. Thread-2 be ready to read data!
  4. Thread-0have read data :null
  5. Thread-2have read data :null
  6. Thread-1have read data :null
  7. Thread-5 be ready to write data!
  8. Thread-5 have write data: 6934
  9. Thread-5 be ready to write data!
  10. Thread-5 have write data: 8987
  11. Thread-5 be ready to write data!
  12. 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. }

  

java中ReentrantReadWriteLock读写锁的使用的更多相关文章

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

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

  2. java多线程:并发包中ReentrantReadWriteLock读写锁的原理

    一:读写锁解决的场景问题--->数据的读取频率远远大于写的频率的场景,就可以使用读写锁.二:读写锁的结构--->用state一个变量.将其转化成二进制,前16位为高位,标记读线程获取锁的次 ...

  3. Java中的读写锁

    一.读写锁 1.初识读写锁 a)Java中的锁——Lock和synchronized中介绍的ReentrantLock和synchronized基本上都是排它锁,意味着这些锁在同一时刻只允许一个线程进 ...

  4. java中的读/写锁

    读写锁接口:ReadWriteLock,它的具体实现类为:ReentrantReadWriteLock 使用场景: 对于一个资源,读读能共存,读写不能共存,写写不能共存. 锁降级:从写锁变成读锁: 锁 ...

  5. 22、Java并发性和多线程-Java中的读/写锁

    以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...

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

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

  7. ReentrantReadWriteLock读写锁详解

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

  8. ReentrantReadWriteLock读写锁的使用

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

  9. ReentrantReadWriteLock读写锁的使用2

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

随机推荐

  1. Java基础知识强化之集合框架笔记75:哈希表

    1. 哈希表数据结构(数组): 2. 哈希表确定元素是否相同: (1)判断的是两个元素的哈希值是否相同                     如果相同,再判断两个对象内容是否相同 (2)判断哈希值相 ...

  2. javascript编程的最佳实践推荐

    推荐的javascript编程的最佳实践,摘要记录在这里: 可维护的代码保证代码的性能部署代码 1 可维护的代码1.1什么是维护的代码:可理解性——其他人可以接手代码并理解它的意图和一般途径,而无需原 ...

  3. oracle 10g升级到11g

    Linux 上Oracle RAC 10g 升级到 Oracle RAC 11g 了解如何在 Oracle Enterprise Linux 5 上逐步将 Oracle RAC 10g 第 2 版升级 ...

  4. linux安装gcc的一些问题。

    输入命令:yum install gcc 提示: Loaded plugins: fastestmirror, langpacksExisting lock /var/run/yum.pid: ano ...

  5. js实现归并排序

    function merge(s_arr, d_arr, start, middle, end){ var s_temp = start; var m_temp = middle+1; var tem ...

  6. poj 2411 状态压缩dp

    思路:将每一行看做一个二进制位,那么所有的合法状态为相邻为1的个数一定要为偶数个.这样就可以先把所有的合法状态找到.由于没一层的合法状态都是一样的,那么可以用一个数组保存.由第i-1行到第i行的状态转 ...

  7. Mirco2440核心板设计思考

    1.核心板架构 注意的是:此处的RAM和ROM都是外置的 硬件框架 S3C2440+ SDRAM + NAND Flash + NOR Flash 也就是 CPU + RAM + ROM 2.S3C2 ...

  8. Nginx - HTTP Configuration, Module Directives

    Socket and Host Configuration This set of directives will allow you to configure your virtual hosts. ...

  9. Android 中的图像特效(Matrix)

    以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,现在在Android中有一个Matrix类,它的中文意思就是矩阵.Matrix主要是用于图像的缩放.平移.旋转.扭曲等操作.图像处理,主要用到的 ...

  10. money 转换成 varchar

    Sql :cast(sum(colname) as varchar) 或者 convert(varchar,sum(colname)) ),sum(colname))