AQS:
java 锁的核心抽象类:
主要的思想,就是 violate 的 state + cas 来模拟,加锁 和解锁的操作;
waiting 的列表,使用的是一个 线程队列。
不同于 synchronizer 用的是 moniter enter/exit 特殊指令; 加 mointer对象(也包含,等待队列,当前线程等;)
每次进入moniter标识的区间,就会检查响应对象的monitor对象,当前线程,重入次数;等待队列等等;
======================
AQS 的思想,可以锁基本和 moniter是一样的。 等待列表, 计数state,当前线程。
其中 state 的取值范围是 0/1,代表独占锁,取大于0的值的时候,代表的是共享锁;
其中等待队列,用来处理 公平和非公平的问题;
=======AQS 有5个抽象方法,是需要更具自己的需求去实现的。
tryAcquire
tryRelease
tryAcquireShared
tryReleaseShared
isHeldExclusively
以可重入lock为例:
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;
}
就是在实现 tryAcquire;
cas 设置状态:如果 state >0, 但是当前线程是持有锁的线程,就计数增加;
==== 在看额countlatch,是一个典型的 shared 锁的 机制:
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
countLatch, 初始化的时候,就把 state 设置为 比如10;
countLatch. await() 的就是尝试获得锁; 但是 state!=0,肯定是获得不到的。所以等待;
countLatch.release,就是减少state,以便 await的线程能够获得锁;
其他的semphare ,用state来作为permit,permit 为0 的时候无法获取需要wait,不为0 可以获取;
cyclebarrier 使用的是条件condition,一个lock 可以有多个condition,我们可以做到更加灵活的singal 对应的线程; 同样适用一个变量,记录barrier的个数,当达到0的时候,signalall, 通知所有的线程,同时 reseet 变量,可以重复使用,这是和 countlatch不一样的地方;
网友评论