读写锁的应用
读写锁在 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 公布