读写锁

作者: yes的练级攻略 | 来源:发表于2019-04-07 12:00 被阅读0次

今天来说说Java 的读写锁-ReadWriteLock,ReadWriteLock是一个接口,实现类是ReentrantReadWriteLock,看着名字的翻译就是可重入读写锁。

为什么Java会搞了那么多种类的锁,因为不同的场景需要做不同的适配来达到性能和使用的最优,而读写锁的使用场景就是读多写少。

读写锁是什么?

读写锁就是分了两种情况,一种是读时的锁,一种是写时的锁,它允许多个线程同时读共享变量,但是只允许一个线程写共享变量,当写共享变量的时候也会阻塞读的操作。这样在读的时候就不会互斥,提高读的效率。

可重入锁是什么?

可重入锁指的是在同一个线程内如果你的外层函数已经获得了锁,那么当你的内层函数也能获取锁,也就是通过一个线程再次进入同步代码块时可以获得自己已经获得的锁,而不可重入则反之。看下简单的示例


    public void doSth(){   //外层函数
        lock.lock();
        do();  //内层函数
        lock.unlock();
    }
    public void do(){
        lock.lock();
        //do something
        lock.unlock();
     }

可重入锁这样使用上面代码是没问题的,如果不可重入锁这样的调用是不允许的。

来看看Javadoc中ReentrantReadWriteLock的示例,主要说的就是处理一个获取一个缓存数据的示例

 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();
     }
   }
 }

可以看出使用还是简单的,相对于ReentrantLock来说就是多了个角色区别一个是读锁一个是写锁。

读写锁的升降级

上面代码有提到

Must release read lock before acquiring write lock (在获取写锁前必须释放读锁)

也就是说读写锁不允许锁的升级,不能直接从读锁升级到写锁。如果读锁还没有释放,此时获取写锁,会导致写锁永久等待,最终导致相关线程都阻塞,GG。切记不可这样使用

但是锁的降级是允许的

Downgrade by acquiring read lock before releasing write lock(通过在释放写锁之前获取读锁来降级)

也就是说在释放写锁之前可以获取读锁来达到锁的降级!

读写锁还有一点不同就是写锁是支持条件变量的也就是支持newCondition,而读锁是不支持条件变量的,如果读锁调用newCondition会抛UnsupportedOperationException

读写锁实现了java.util.concurrent.locks.Lock接口,所以tryLock()、lockInterruptibly()等方法都是支持的,并且也支持公平锁和非公平锁的模式,底层是也是基于AbstractQueuedSynchronizer实现的,所以对于公平和非公平锁的实现可以参见面试官:说说Java中的信号量?Semaphore 我的这篇文章


如有错误欢迎指正!更多知识分享可关注我

个人公众号:yes的练级攻略

相关文章

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

  • 线程同步(下)

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

  • 可重入读写锁 ReentrantReadWriteLock

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

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

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

  • 线程安全之读写锁

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

  • ReadWriteLock读写锁

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

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

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

  • Go 语言的锁

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

  • 读写锁实现

    读写锁 ReentrantReadWriteLock可重入读写锁(实现ReadWriteLock接口) 使用:Re...

  • 读写锁和互斥锁的区别

    同步 互斥锁 读写锁 区别

网友评论

      本文标题:读写锁

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