• 读写锁


    锁维护了一对锁,一个读锁和一个写,通分离读锁和写锁,使得并性相比一般的排他有了很大提升 

    一般情况下,的性能都会比排它好,因大多数是多于写的。在多于写的情况下,提供比排它更好的并性和吞吐量。Java包提供实现是ReentrantReadWriteLock,它提供的特性如表所示。 

    的接口与示例

    ReadWriteLock读锁和写的两个方法,即readLock()方法和writeLock()方法,而其实现——ReentrantReadWriteLock,除了接口方法之外,提供了一些便于外界控其内部工作状的方法,些方法以及描述如表所示 

    一个的使用方式的缓存示例:

    public class Cache {
      static Map<String, Object> map = new HashMap<String, Object>();
      static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
      static Lock r = rwl.readLock();
      static Lock w = rwl.writeLock();
      // 获取一个key对应的value
      public static final Object get(String key) {
        r.lock();
        try {
          return map.get(key);
        } finally {
          r.unlock();
        }
      }
      // 设置key对应的value,并返回旧的value   public static final Object put(String key, Object value) {     w.lock();     try {       return map.put(key, value);     } finally {       w.unlock();     }   }
      // 清空所有的内容   public static final void clear() {     w.lock();     try {       map.clear();     } finally {       w.unlock();     }   } }

     上述示例中,Cache合一个非线程安全的HashMap为缓存的实现,同使用的读锁和写来保Cache线程安全的。在操作get(String key)方法中,需要读锁使得并发访问该方法不会被阻塞。写操作put(String key,Object value)方法和clear()方法,在更新HashMap提前取写,当取写后,其他线读锁和写取均被阻塞,而只有写放之后,其他写操作才能继续Cache使用提升操作的并性,也保证每次写操作所有的写操作的可性,同时简化了程方式。 


    实现分析 (以下没有特别说均可认为ReentrantReadWriteLock ):

    1. 写状设计
    2. 取与释放
    3. 读锁取与

    1.写状设计

    自定同步器来实现同步功能,而写状就是其同步器的同步状。回想ReentrantLock中自定同步器的实现,同步状表示被一个线程重复取的次数,而的自定同步器需要在同步状(一个整型量)上维护多个读线程和一个写线程的状态,使得设计为读锁实现的关

     如果在一个整型量上维护多种状,就一定需要按位切割使用量,量切分成了两个部分,高16位表示,低16位表示写,划分方式如5-8所示。
     

    当前同步状表示一个线程已经获取了写,且重入了两次,同连续获取了两次读锁。 是通位运算来确定和写各自的状态。当前同步状态值为S,写状等于S&0x0000FFFF(将高16位全部抹去),等于S>>>16(无符号右移16位)。当写状增加1,等于S+1,当增加1,等于S+(1<<16),也就是S+0x00010000


     2.取与放 

    是一个支持重入的排它。如果当前线程已经获取了写增加写状

    //ReentrantReadWriteLock的tryAcquire方法
    protected final boolean tryAcquire(int acquires) {
      Thread current = Thread.currentThread();
      int c = getState();
      int w = exclusiveCount(c);
      if (c != 0) {
        // 存在读锁或者当前获取线程不是已经获取写锁的线程
        if (w == 0 || current != getExclusiveOwnerThread())
          return false;
        if (w + exclusiveCount(acquires) > MAX_COUNT)
          throw new Error("Maximum lock count exceeded");
        setState(c + acquires);
        return true;
      }
      if (writerShouldBlock()
    || !compareAndSetState(c, c + acquires)) {     return false;   }
      setExclusiveOwnerThread(current);   
    return true; }

     方法除了重入条件(当前线为获取了写线程)之外,增加了一个读锁是否存在的判断。 

    放与ReentrantLock程基本似,每次放均减少写状,当写状态为0表示写已被放,从而等待的线程能够继续访问读,同前次写线程的修改续读线程可

    3.读锁取与

     



  • 相关阅读:
    关于webpack的cdn配置
    谁都能听懂的Redux+Redux-Saga超级傻瓜教程
    记一个react拖动排序中的坑:key
    es6 解构写法:给变量取别名
    C++新型强制类型转换。
    C++ new、delete、namespace关键字。
    C++ 调用C语言、extern "C"、__cplusplus关键字
    C++ 重载函数
    liunx 环境下安装 Eclipse C++
    C++ 内联函数 inline关键字
  • 原文地址:https://www.cnblogs.com/jimboi/p/6412613.html
Copyright © 2020-2023  润新知