重入锁和读写锁
ReentrantLock,重入锁,支持重新进入的锁:即某线程在获取到锁之后,可以再次获取锁而不会被阻塞。
其主要特性如下:
支持重入:通过组合自定义同步器来来实现重入特性
synchronized关键字也隐式地支持重进入,比如synchronized修饰的递归方法,在方法执行时,执行线程在获取了锁之后仍能连续多次地获得该锁,不会出现阻塞自己的情况;
支持公平地获取锁:获取锁的顺序与请求锁的顺序是相同的,等待时间最长的线程最优先获取到锁。
支持绑定多个Condition。
非公平获取锁重进入的实现
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}else if (current == getExclusiveOwnerThread()) {
//如果是当前持有锁的线程再次获取锁,则将同步值进行增加并返回true
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}公平锁重进入的实现
与非公平获取锁的方法nonfairTryAcquire(int acquires)相比,多了一个hasQueuedPredecessors()判断:同步队列中当前节点(当前想要获取锁的线程)是否有前驱节点,如果该方法返回true,则表示有线程比当前线程更早地请求获取锁,因此需要前驱线程获取并释放锁之后才能继续获取锁。
公平锁保证了锁的获取按照FIFO原则,而代价是进行大量的线程切换; 非公平锁虽然可能造成线程“饥饿”(即某线程可能需要等很久才得到锁),但线程切换极少,可以保证更大的吞吐量。
ReentrantReadWriteLock
ReentrantLock在同一时刻,只允许一个线程进行访问(无论读还是写)。而读写锁是指:在同一时刻,允许多个线程进行读操作,而写操作则会阻塞其他所有的线程(无论是读还是写,都会被阻塞)。读写锁维护了一对锁:读锁和写锁,通过分离读锁和写锁,使得并发性能相比一般的排他锁有了很大的提升。
它的特性如下:
重进入;
公平性选择
锁降级:写锁可以降级为读锁,
此外,ReentrantReadWriteLock还提供了一些便于外界监控其内部状态的方法,如下:
示例:使用ReentrantReadWriteLock实现Cache
TODO:读写锁的实现原理
Last updated