java中的读写锁 ReentrantReadWriteLock

业务需要今天正式使用了读写锁 ReentrantReadWriteLock,能比ReentrantLock有更高的并发数,记录一波。

之前文章有介绍过 synchronized 和 ReentrantLock ,这次要说的 ReentrantReadWriteLock ,看起来和ReentrantLock 很像对吧,但场景用对了它们还是有不小的性能差距的哦。ReentrantLock是一个排他锁的实现,同时只能有一个线程去加锁操作执行,而ReentrantReadWriteLock允许多个读线程同时访问,但是不允许多个写线程同时访问,在我们实际应用中例如缓存等共享数据的访问都是读操作要远多于写操作的。

知识点梳理

读写锁

ReadWriteLock管理一组锁,一个是只读的锁,一个是写锁。ReetrantReadWriteLock读写锁的实现中,读锁使用共享模式,写锁使用独占模式,换句话说,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。当有读锁时,写锁就不能获得;而当有写锁时,除了获得写锁的这个线程可以获得读锁外,其他线程不能获得读锁。

锁获取顺序(是否公平锁)

和ReentrantLock相同,锁的获取顺序也是会影响锁效率的一个因素。

  • 非公平模式(默认)
    当以非公平初始化时,读锁和写锁的获取的顺序是不确定的。非公平锁主张竞争获取,可能会延缓一个或多个读或写线程,但是会比公平锁有更高的吞吐量。
  • 公平模式
    当以公平模式初始化时,线程将会以队列的顺序获取锁。当当前线程释放锁后,等待时间最长的写锁线程就会被分配写锁;或者有一组读线程组等待时间比写线程长,那么这组读线程组将会被分配读锁。

可重入

顶着Reentrant开头的锁,可重入也是很重要的特性啦,重入简单理解就是可以重复,就是说一个线程内可以多次获取锁(不释放锁多次加锁),这里还有一个要点说,加锁几次就需要解锁几次,否则会出现死锁!!!

锁升级

锁升级指的是本线程已持有读锁还要继续获取写锁,这里要注意啦,ReentrantReadWriteLock 是不支持锁升级的!原因也很简单读写操作是互斥,需要等所有读锁释放后才可以加写锁。

锁降级

锁降级自然是写锁持有时想要获取读锁,这个操作是支持的,但是依然需要根据顺序(后加的锁先解)对应的释放读写锁,否则还是会出现死锁导致其他线程无法获得锁。