ReentrantLock 非公平锁加锁解锁简要过程, 不考虑可重入, 打断之类的细节
NonfairSync关键字段:
state: 0表示共享, 1表示已被占用, 即状态为0时可已被加锁
head, tail: 维护一个双向链表, 存的是被park的线程(具体是什么状态看waitStatus), 尾进, 头出
exclusiveOwnerThread: 当前所被哪个线程持有
加锁:
成功:
state被置为1 (cas)
owner设置为当前线程
失败 阻塞:
1. addWaiter(Node.EXCLUSIVE): 在双线链表中加入一个节点, 关联当前线程(此时仅仅是加入, 还没有被阻塞), 返回新节点node
2. acquireQueued(node, arg):
while(true)
(1): 尝试获取锁 若成功获取, 被唤醒的线程的前驱节点(即head)从链表中移除, 然后自己作为head,
因为head只是作为一个方便操作的节点, 没有实际意义, 所以相当于变相把被唤醒的线程移除的链表
(这一步主要是为了被唤醒的线程考虑, 因为之前是阻塞再这个方法中的, 所以被唤醒后仍然在这里继续执行, 那被唤醒后的第一件事, 就是考虑争抢锁)
(2): 获取失败, 把前驱节点的waitStatus改为-1, 然后park
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// 尝试获取锁
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 这里park
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
释放锁:
1. state改为0
2. ownerThread置为null
3. 从双链表的头开始唤醒线程(LockSupport.unpark(s.thread);)
ReentrantLock加锁解锁大致流程
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...