java.util.concurrent.ThreadPoolExecutor内部类Worker继承了AbstractQueuedSynchronizer,这个不说了,说说ReentrantLock吧。
从创建锁对象开始,有的同学之前已经注意到了,创建对象的时候是可以加参数的。
ReentrantLock rl1=new ReentrantLock(false);
ReentrantLock rl2=new ReentrantLock(true);
如果是true的时候返回公平锁,否则返回非公平锁,到了这里我就看不懂了,什么是公平锁,什么又是非公平锁呢。
查看了代码后,发现代码上是有区别的,先上公平锁的代码
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
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;
}
这里注意那段e文的注释:
tryacquire的公平版本。不要授权访问,除非递归调用或没有等待者(Runnable)或者是第一个。
再对比看看非公平版的:
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
再看看nonfairTryAcquire这个方法
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;
}
Performs non-fair tryLock. tryAcquire is implemented in subclasses, but both need nonfair try for trylock method.实现非公平trylock。tryacquire是在子类中实现,但都需要非公平实现tryLock方法,这句有待斟酌。
对比代码发现以下
1.公平模式下tryacquire判断条件上多了hasQueuedPredecessors()这个方法。
2.非公平模式下lock方法先执行了compareAndSetState(0, 1)方法。
hasQueuedPredecessors() 这个方法是用来查询是否有比当前线程等待了更长时间。返回true,说明当前线程前面有一个排队的线程,返回false说明当前线程是队列中的头结点或者队列为空。
也就是说公平模式下是谁等待的时间长谁优先,类似FIFO的性质,而非公平模式下则是谁先抢到谁执行了(红色部分待验证)。
下面来看看compareAndSetState(0, 1)方法如果当前状态值等于期望值自动设置同步状态的更新;此操作具有读取的内存
看一下Node中的状态
/** waitStatus value to indicate thread has cancelled */
static final int CANCELLED = 1;
/** waitStatus value to indicate successor's thread needs unparking */
static final int SIGNAL = -1;
/** waitStatus value to indicate thread is waiting on condition */
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/
static final int PROPAGATE = -3;
最近有朋友推荐了下面这篇,打算看完后更新下心得。
https://javadoop.com/2017/06/16/AbstractQueuedSynchronizer/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io