ReentrantLock
还不是很明白
参考
彤哥读源码
https://blog.csdn.net/u010805617/article/details/87260475
简介
ReentrantLock是Java SE 5新增的jdk层面实现可重入锁的功能, 提供了与synchronized类似的同步功能,只是在使用时需要显示的获取和释放锁。虽然缺少了隐私获取和释放锁的便捷性,但是缺拥有了锁获取和释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字不具备的同步特性。同时也提供了获取和释放锁的灵活性。
公平锁和非公平锁
ReentrantLock提供了两种锁特性:公平锁和非公平锁,公平锁和非公平锁的区别是:
如果在绝对时间上,先对锁进行获取的请求一定先被满足,那么这个锁是公平的,反之,是不公平的。公平的获取锁,也就是等待时间最长的线程最优先获取锁,也可以说锁获取是顺序的。ReentrantLock提供了一个构造函数,能够控制锁是否是公平的。
事实上,公平的锁机制往往没有非公平的效率高,但是,并不是任何场景都是TPS作为唯一的指标,公平锁能够减少“饥饿”发生的概率,等待越久的请求越是能够到优先满足。
源码实现
/**
* lock锁的同步控制,子类有公平和非公平两个版本。
* 该抽象锁同步器主要提供了尝试获取(非公平实现)和尝试释放锁等功能
**/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
// 获取锁,由子类实现
abstract void lock();
// 执行非公平的尝试获取锁操作。
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 如果锁没有被占用,则尝试获取锁
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 通过判断当前线程是否为获取锁的线程来决定获取操作是否成功,如果是获取锁的线程
// 再次请求,则将同步状态值进行增加并返回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;
}
// 如果该锁被获取了n次,那么前(n-1)次tryRelease(int releases)方法必须返回false,而只有
// 同步状态完全释放了,才能返回true。可以看到,该方法将同步状态是否为0作为最终释放
// 的条件,当同步状态为0时,将占有线程设置为null,并返回true,表示释放成功。
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);
}
setState(c);
return free;
}
// 判断是否当前线程独占锁
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
公平锁
/**
* 继承Sync, 并实现公平锁
**/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
// 阻塞获取锁
final void lock() {
acquire(1);
}
// 尝试获取锁(公平策略),不能保证获取,除非递归调用或没有其他的线程等待获取锁
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;
}
}
非公平锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
// 阻塞获取锁, 当前线程优先去获取锁,获取失败在通过队列的方式获取
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
// 非公平的方式尝试获取锁
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}