//默认实现为非公平锁,这个构造方法相当于new ReentrantLock(false) false 使用非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
//判断当前线程是否被中断
if (Thread.interrupted())
throw new InterruptedException();
//2种方式获取锁方法
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
//try Acquire(arg) 最终会调用这个方法
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//获取当前锁状态
int c = getState();
//如果锁是空闲时
if (c == 0) {
//cas 更改state值
if (compareAndSetState(0, acquires)) {
//成功的话设置当前锁的独占线程为当前线程
setExclusiveOwnerThread(current);
return true;
}
}
//锁已经被持有且持有者为当前线程
else if (current == getExclusiveOwnerThread()) {
//state增加
int nextc = c + acquires;
//如果增加后小于0.则报错
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//设置新state值
setState(nextc);
return true;
}
return false;
}
//以独占定时模式获取锁 ,在指定时间nanosTimeout内不断获取锁,并且始终都是当前节点的上一个节点先获取到锁
//应该是公平锁的获取方式
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
//获取到超时的时间点
final long deadline = System.nanoTime() + nanosTimeout;
//加入队列末尾
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
//获取当前节点的上一个节点
final Node p = node.predecessor();
//如果是头节点且获取锁成功 tryAcquire(非公平锁方法)
if (p == head && tryAcquire(arg)) {
//将头节点变为当前节点
setHead(node);
//头节点认为设置null,方便垃圾回收
p.next = null; // help GC
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
//如果超时,则直接返回
if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
//虚假中断
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
//失败的话,取消获取
if (failed)
cancelAcquire(node);
}
}
//加入等待队列
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//最新的对尾元素
Node pred = tail;
//如果队列存在
if (pred != null) {
node.prev = pred;
//设置当前队尾元素为当前任务
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
//初始化队列
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
//设置当前头元素
if (compareAndSetHead(new Node()))
tail = head;
} else {
//加入队为
node.prev = t;
//设置当前队尾元素
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
//说明需要通知后续节点
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
//大于0说明该抢锁任务被取消了
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
//waitStatus 为0 或者-3时 说明需要重试 设置waitStatus的值
//设置一个信号量,为后续唤醒
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
//公平锁的加锁方式
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;
}
AQS源码解析
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 开发中需要注意,一定要在finally块中释放锁。 公平锁的解锁过程 tryRelease(arg):该方法有AQ...