ReentrantReadWriteLock 读写锁
定义:一个资源能够被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程,只有在读多写少的情况下,读写锁才有较高的性能体现。
缺点: 1、写锁饥饿问题,如果读锁特别多,写锁特别少,会导致写锁抢不到资源
2、锁降级
锁降级:如果一个线程持有了写锁,在没有释放写锁的情况下,他还可以继续获得读锁,这就是写锁的降级,降级为了读锁。
锁降级需要遵循获取写锁、获取读锁,再释放写锁的次序,写锁才能够降级为读锁。
在ReentrantReadWriteLock中,当读锁被使用时,如果有线程尝试获取写锁,该写线程会被阻塞。所以需要释放所有读锁,才可以获取写锁。写锁和读锁是互斥的(这里的互斥是指线程间的互斥,当前线程可以获取到写锁又获取到读锁,但是获取到了读锁不能继续获取写锁),这是因为读写锁要保持写操作的可见性。因为,如果允许读锁在被获取的情况下对写锁的获取,那么正在运行的其他读线程无法感知到当前写线程的操作。因此,分析读写锁ReentrantReadWriteLock,会发现它有个潜在的问题:
读锁结束,写锁有望;写锁独占,读写全堵;
如果有线程正在读,写线程需要等待读线程释放锁后才能获取写锁。
即ReentrantReadWriteL ock读的过程中不允许写,只有等待线程都释放了读锁,当前线程才能获取写锁,也就是写入必须等待,这是一种悲观的读锁,人家还在读着那,你先别去写,省的数据乱。
StampLock邮戳锁
StampLock是对读写锁的一个优化,在读的过程中也允许写锁介入,来解决写锁饥饿问题
加锁会返回一个stamp,stamp为零表示获取失败,其余为获取成功。
当释放锁和转换锁的时候需要传入stamp,必须和获取锁时得到的stamp一直,返回true说明值未被更改,false说明值被更改过,需要升级为悲观读重新读取。
StampLock的三种访问模式:
1:Reading(悲观读):和ReentrantReadWriteLock的读类似。
2、Writing(写模式):和ReentrantReadWriteLock的写类似。
3、Optimistic reading(乐观读):无所机制,类似于数据库的乐观锁,支持读写并发,乐观的认为读时没人修改,加入被修改升级为悲观读模式。
缺点: 1、StampLock不支持重入,如果一个线程已经持有了写锁,再去获取写锁的时候就会造成死锁。
2、StampLock的悲观读锁和写锁都不支持条件变量Condition。
3、使用StampLock的时候一定不要调用中断操作,即不要调用interrupt()方法。
标签:ReentrantReadWriteLock,写锁,读写,StampedLock,获取,读锁,线程,邮戳 From: https://www.cnblogs.com/tyleaf/p/17007192.html