JUC之ReentrantLock
一、什么是ReentrantLock
ReentrantLock就是可重入锁,它主要实现了以下两种机制:
- 可重入,一个线程可以重复获取该锁。
- 公平性,它实现了公平锁与非公平锁。
- 前者能够解决饥饿问题,但是会耗费进百倍的性能
- 后者可能会造成饥饿问题,但是,性能更好。
- 可重入锁,它本身是一个独占锁。
二、ReentrantLock的实现
1、重入机制的实现
- 解决重入问题
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//计数为0,无需解决重入问题,直接CAS获取
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//否则存在线程占有,判断是否是当前线程,如果是,计数++
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
//重入过多,出现溢出。
if (nextc < 0)
//出现栈溢出
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
- 解决重入释放问题
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//重入N次,知道释放N次,才返回true,否则一直都是false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
2、公平机制的实现
- fair
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//必须是队列头才有机会获取
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
- unfair
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()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
三、ReentrantLock的应用
在java中,基本上所有的锁都是可重入锁,因为可重入锁本身就是为了避免死锁问题,死锁从某种意义上讲是一种错误的行为,为了纠正这种行为,所有的锁都设计成可重入锁。以下是重入锁的一些应用:
- ReentrantReadWriteLock
- ReadLock
- WriteLock
- CyclicBarrier
来源:https://blog.csdn.net/rekingman/article/details/98886817