• 读写锁(ReadWriteLock)的使用


    Definition

    读写锁包含一对相关的锁,读锁用于只读操作,写锁用于写操作。读锁可能由多个读线程同时运行,写锁是唯一的。

    Direction

    1、读锁和写锁之间是互斥的,同一时间只能有一个在运行。但是可以有多个线程同时读取数据。

    2、写入数据之前必须重新确认(ReCheck)状态,因为其他的线程可能会拿到写锁再一次修改我们已经修改过的值。这是因为前一个线程拿到写锁之后,后面的线程会被阻塞。当前一个线程释放写锁之后,被阻塞的线程会继续运行完成被阻塞的部分代码,所以才会出现这样的情况。

    3、当某一个线程上了写锁之后,自己仍然可以上读锁,之后在释放写锁,这是一种降级(Downgrade)的处理方法。

    Method

    读写锁(ReadWriteLock)包含如下两个方法:

    1.读锁

    Lock readLock()

    2.写锁

    Lock writeLock()

    Example

    以下代码在开始读数据的时候上读锁,当有一个线程发现没有数据时,释放读锁,上写锁,开始写入数据。

    数据写入完成后释放写锁,并还原成读锁,实现了简单的读和写之间的互斥。

    示例代码:

        private ReadWriteLock rwl = new ReentrantReadWriteLock();//定义读写锁
        public Object getData(String key){
            //使用读写锁的基本结构
            rwl.readLock().lock();
            Object value = null;
            try{
                value = cache.get(key);
                if(value == null){
                    rwl.readLock().unlock();
                    rwl.writeLock().lock();
                    try{
                        // Recheck state because another thread might have
                        // acquired write lock and changed state before we did.
                        if(value == null){
                            value = "aaaa";//写入数据
                        }
                    }finally{
                        rwl.writeLock().unlock();
                    }
                    rwl.readLock().lock();
                }
            }finally{
                rwl.readLock().unlock();
            }
            return value;
        }

    读写锁的完整使用示例:

     1 public class Test {
     2     public static void main(String[] args) {
     3         final Queue q = new Queue();
     4         for(int i=0;i<3;i++)
     5         {
     6             new Thread(){
     7                 public void run(){
     8                     while(true){
     9                         q.get();                        
    10                     }
    11                 }
    12             }.start();
    13 
    14             new Thread(){
    15                 public void run(){
    16                     while(true){
    17                         q.put(new Random().nextInt(10000));
    18                     }
    19                 }        
    20             }.start();
    21         }
    22     }
    23 }
    24 
    25 class Queue{
    26     private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
    27     ReadWriteLock rwl = new ReentrantReadWriteLock();
    28     public void get(){
    29         rwl.readLock().lock();
    30         try {
    31             System.out.println(Thread.currentThread().getName() + " be ready to read data!");
    32             Thread.sleep((long)(Math.random()*1000));
    33             System.out.println(Thread.currentThread().getName() + "have read data :" + data);            
    34         } catch (InterruptedException e) {
    35             e.printStackTrace();
    36         }finally{
    37             rwl.readLock().unlock();
    38         }
    39     }
    40     
    41     public void put(Object data){
    42         rwl.writeLock().lock();
    43         try {
    44             System.out.println(Thread.currentThread().getName() + " be ready to write data!");                    
    45             Thread.sleep((long)(Math.random()*1000));
    46             this.data = data;        
    47             System.out.println(Thread.currentThread().getName() + " have write data: " + data);                    
    48         } catch (InterruptedException e) {
    49             e.printStackTrace();
    50         }finally{
    51             rwl.writeLock().unlock();
    52         }
    53     }
    54 }

    部分输出结果如下:

    Thread-0 be ready to read data!
    Thread-2 be ready to read data!
    Thread-4 be ready to read data!
    Thread-4have read data :null
    Thread-0have read data :null
    Thread-2have read data :null
    Thread-3 be ready to write data!
    Thread-3 have write data: 9763
    Thread-3 be ready to write data!
    Thread-3 have write data: 5187
    Thread-3 be ready to write data!
    Thread-3 have write data: 2135
    Thread-1 be ready to write data!
    Thread-1 have write data: 180
    Thread-1 be ready to write data!
    Thread-1 have write data: 5979
    Thread-1 be ready to write data!
    Thread-1 have write data: 9495
    Thread-1 be ready to write data!
    Thread-1 have write data: 6363
    Thread-1 be ready to write data!
    Thread-1 have write data: 31
    Thread-1 be ready to write data!
    Thread-1 have write data: 7530
    Thread-1 be ready to write data!
    Thread-1 have write data: 1354
    Thread-5 be ready to write data!
    Thread-5 have write data: 3580
    Thread-5 be ready to write data!
    Thread-5 have write data: 5534
    Thread-5 be ready to write data!
    Thread-5 have write data: 2522
    Thread-5 be ready to write data!
    Thread-5 have write data: 2926
    Thread-4 be ready to read data!
    Thread-0 be ready to read data!
    Thread-2 be ready to read data!
    Thread-2have read data :2926
    Thread-0have read data :2926
    Thread-4have read data :2926
    
  • 相关阅读:
    76、HTTP如何禁用缓存?如何确认缓存?
    多态与多态性,鸭子类型,内置方法,反射,异常处理
    继承的应用,继承实现原理,super(),多继承的代码规范,组合
    类的装饰器,绑定方法与非绑定方法,继承,继承背景下的属性查找
    面向对象,类与对象,__nit__方法,属性查找,隐藏属性
    xml模块、hashlib模块、subprocess模块、os与sys模块、configparser模块
    模块:re,json,pickle,time , datetime,random,猴子补丁
    区分py文件的两种用途,包的介绍和使用,日志模块
    模块的概念、使用,搜索路径与优先级,软件开发的目录规范
    三元表达式,列表、字典、集合生成式,生成器表达式,函数递归,匿名函数,面向过程编程
  • 原文地址:https://www.cnblogs.com/shen-smile/p/5142292.html
Copyright © 2020-2023  润新知