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加锁解锁大致流程
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。