读写锁的应用
读写锁在 Java 中是 ReentrantReadWriteLock,应用形式是:
import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockDemo implements TestDemo { ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); ReentrantReadWriteLock.ReadLock readLock = lock.readLock(); ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); private int x = 0; private void count() { writeLock.lock(); try { x++; } finally { writeLock.unlock();// 保障当读的时候如果出现异常,会开释锁,synchronized为什么不必呢?因为synchronized外部曾经帮咱们做了~ } } private void print(int time) { readLock.lock(); try { for (int i = 0; i < time; i++) { System.out.print(x + " "); } System.out.println(); } finally { readLock.unlock();// 保障当读的时候如果出现异常,会开释锁,synchronized为什么不必呢?因为synchronized外部曾经帮咱们做了~ } } @Override public void runTest() { }}
ReentrantReadWriteLock和ReentrantLock的区别?
应用ReentrantReadWriteLock读写锁的形式,会调用readLock()和writeLock()两个办法,看下他们的源码:
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
复制代码能够看到用到了WriteLock和ReadLock两个动态外部类,他们对锁的实现如下:
public static class ReadLock implements Lock, java.io.Serializable { public void lock() { sync.acquireShared(1); //共享 } public void unlock() { sync.releaseShared(1); //共享 }}public static class WriteLock implements Lock, java.io.Serializable { public void lock() { sync.acquire(1); //独占 } public void unlock() { sync.release(1); //独占 }}abstract static class Sync extends AbstractQueuedSynchronizer {}
看到这里发现了ReentrantReadWriteLock和ReentrantLock的一个相同点和不同点,
雷同的是应用了同一个要害实现AbstractQueuedSynchronizer,不同的是ReentrantReadWriteLock应用了两个锁别离实现了AQS,
而且WriteLock和ReentrantLock一样,应用了独占锁。
而ReadLock和Semaphore一样,应用了共享锁。
再往下的内容预计看过后面几篇文章的都很相熟了,独占锁通过state变量的0和1两个状态来管制是否有线程占有锁,共享锁通过state变量0或者非0来管制多个线程拜访。
在下面的代码中,ReadLock和WriteLock应用了同一个AQS,那么在ReentrantReadWriteLock中又是怎么管制读锁和写锁关系的呢?
这当中还有一个问题,因为16位最大全1示意为65535,所以读锁和写锁最多能够获取65535个。
ReentrantReadWriteLock会产生写饥饿的状况吗?如果产生,有没有比拟好的解决办法?
ReentrantReadWriteLock也会产生写申请饥饿的状况,因为写申请一样会排队,
不论是偏心锁还是非偏心锁,在有读锁的状况下,都不能保障写锁肯定能获取到,这样只有读锁始终占用,就会产生写饥饿的状况。
那么JDK就没有提供什么好方法来解决这个问题吗?
当然是有的,那就是JDK8中新增的改良读写锁---StampedLock.
本文由猿必过 YBG 公布