美文网首页
17.读写锁ReentrantWriteReadLock

17.读写锁ReentrantWriteReadLock

作者: 0x70e8 | 来源:发表于2018-08-08 10:15 被阅读0次

读写锁ReentrantWriteReadLock,基于AQS的锁机制,实现ReadWriteLock接口。内部有两个锁,一个读锁和一个写锁,将AQS的state分成高16位和低16位作为信号量分给这两个锁使用。

特性

  • 读锁共享
  • 写锁互斥(也和读锁互斥)
  • 可重入,写锁递归重入最大个数为1<< 16,读锁共享或递归重入最大数也是1<<16(因为共用了int型的state)
  • 写锁可以降级为读锁,反之不行。

读写锁的使用主要在于其读锁可以共享,使得读操作较多的操作能高效并发。

读写锁的使用

  • 创建锁对象
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Lock readLock = readWriteLock.readLock();
Lock writeLock = readWriteLock.writeLock();
  • 读写锁保护临界区
readLock.lock();
try{
// 只读操作
}finally{
    readLock.unlock();
}


writeLock.lock();
try{
    //写操作
}finally{
    writeLock.unlock();
}
  • 写锁降级(锁降级是为了让读线程及时感知到数据的变化。)
class CachedData {
   Object data;
   volatile boolean cacheValid;
   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {
     rwl.readLock().lock();
     if (!cacheValid) {
       // Must release read lock before acquiring write lock
       rwl.readLock().unlock();
       rwl.writeLock().lock();
       try {
         // Recheck state because another thread might have
         // acquired write lock and changed state before we did.
         if (!cacheValid) {
           data = ...
           cacheValid = true;
         }
         // 锁降级,此时锁为读锁,其他读线程可以读取到刚刚写入的值,但是其他的写线程不能抢占来修改上面刚刚改的数据,这一步保证了数据的有效期直到释放读锁。(只有释放了读锁写线程才能竞争锁)
         // Downgrade by acquiring read lock before releasing write lock
         rwl.readLock().lock();
       } finally {
         rwl.writeLock().unlock(); // Unlock write, still hold read
       }
     }

     try {
       use(data);
     } finally {
       rwl.readLock().unlock();
     }
   }
 }

如果上面示例代码不使用锁降级,只在最后的finally中释放写锁,那么当数据在本线程中修改之后,其他的读线程并不能感知,因为他们都阻塞了,数据的改变能一直维持到此线程释放写锁,其他读线程才有可能读到此线程写的值,但仅仅是可能,因为此线程释放写锁后,可能一个写线程抢占了锁,又一次修改了值,那么这个线程的修改其实对其他读线程来说,可能是不可见的。

原理

读写锁的原理简单来说就是组合了AQS的独占锁和共享锁,并且其内部有一些协作,比如锁降级,写锁和读锁的互斥等。

相关文章

  • 17.读写锁ReentrantWriteReadLock

    读写锁ReentrantWriteReadLock,基于AQS的锁机制,实现ReadWriteLock接口。内部有...

  • Java并发-17.读写锁

    读写锁维护一对锁,读锁和写锁 分离读锁和写锁,并发性比排它锁有很大提升 ReadWriteLock仅定义读锁和写锁...

  • 读写锁和互斥锁 读写互斥锁,简称读写锁 mux sync.RWMutex Lock和Unlock分别对写锁进行锁定...

  • 线程同步(下)

    继上篇。这篇介绍的几种使用的较少。 读写锁 读写锁与互斥锁类似。不过读写锁允许更高的并行性。读写锁可以有三种状态:...

  • 可重入读写锁 ReentrantReadWriteLock

    读写锁分为读锁和写锁,多个线程获取读锁不互斥,读写锁、写写锁互斥。 输出

  • Java并发编程-读写锁(ReentrantReadWriteL

    章节目录 ReentrantReadWriteLock 特性 读写锁接口示例 读写锁的实现分析读写状态设计写锁的释...

  • 线程安全之读写锁

    相关API 初始化读写锁 释放读写锁 获取读锁 获取写锁 解锁 实例

  • ReadWriteLock读写锁

    1、引入ReadWriteLock读写锁 ReadWriteLock是JDK5中提供的读写分离锁。读写分离锁可以有...

  • 基于CAS的一些锁(5)- ReadWriteLock

    ReadWriteLock 读写锁。读写锁的概念其实就是共享锁和排他锁,读锁就是共享锁,写锁就是排他锁。 如何理解...

  • Go 语言的锁

    Go 语言提供两类锁: 互斥锁(Mutex)和读写锁(RWMutex)。其中读写锁(RWMutex)是基于互斥锁(...

网友评论

      本文标题:17.读写锁ReentrantWriteReadLock

      本文链接:https://www.haomeiwen.com/subject/gcdtbftx.html