1、重入锁
表示一个线程可以对资源重复枷锁,支持获取锁时的公平性和非公平性加锁。
公平性:在绝对时间上,先对锁进行获取的请求一定被满足,则此锁是公平的,反之,不公平。
2、获取锁
默认非公平锁
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;
}
判断当前线程是否获取了锁,若获取锁的线程再次请求,则将同步状态值进行增加,并返回true,表示获取同步状态成功。
3)释放锁
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);// 将占有线程置为null
}
setState(c);
return free;
}
释放锁,对应的减少同步状态值。
若该锁获取了n次,那么前(n-1)次tryRelease(int releases)方法返回false,只有同步状态完全释放了,即第n次,才能返回true。
3、公平锁的获取
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;
}
与唯一不同的是多了一个hasQueuedPredecessors()方法,即当前节点是否有前驱节点,若有,则表示有线程比当前线程更早多请求获取锁,需等待前驱线程释放锁之后才能获取锁。
公平性保证了锁的获取按照FIFO的原则,而代价是大量的线程切换;
非公平性虽然会造成线程“饥饿”,但极少的线程切换,保证更大的吞吐量。