当前位置:网站首页>Juc并发编程07——公平锁真的公平吗(源码剖析)
Juc并发编程07——公平锁真的公平吗(源码剖析)
2022-04-23 09:55:00 【半旧518】
先来回顾下公平锁的tryAcquire
代码。
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;
}
}
重点关注注释代码处,如果hasQueuedPredecessors
出现误判会怎么样呢?公平锁是不是就不公平了呀。那我们来研究下hasQueuedPredecessors
,是不是真有百密一疏的情况。
假如线程1已经持有锁了。这个该时候线程2来获取锁,走到hasQueuedPredecessors()
返回false,接着往后面执行CAS
,肯定执行失败,因为现在锁被线程1占有,返回aquire
方法。
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
接着走就是走到addWaiter
的enq
方法。线程2进入等待队列。
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) {
// 此时等head、tail为空,满足`t==null`的条件。
if (compareAndSetHead(new Node())) //这里没有其它线程争抢,成功
tail = head; // 设置成功
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
假设线程2走到注释截至处,现在有一个线程3来抢锁。当它判断等待队列时hasQueuedPredecessors
会返回false,因为h==t
。
public final boolean hasQueuedPredecessors() {
Node t = tail;
Node h = head;
Node s;
return h != t && //不满足条件
((s = h.next) == null || s.thread != Thread.currentThread());
}
那么问题来了,实际上等待队列中应该有线程2,现在我们却得出了等待队列为空的判断呀,线程3不的直接走CAS
吗,万一线程1刚好释放锁了,线程3就插队了阿。由此可见,公平锁并不公平。
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;
}
}
用一张图来总结下上面的过程。
公平锁公不公平关键就在与hasQueuedPredecessors
是否会出现误判。
版权声明
本文为[半旧518]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_41708993/article/details/124336106
边栏推荐
- 第二章 Oracle Database In-Memory 体系结构(上) (IM-2.1)
- Leetcode question bank 78 Subset (recursive C implementation)
- Yarn资源调度器
- Skill point digging
- 【无标题】
- Introduction to graph theory -- drawing
- High paid programmer & interview question series 91 limit 20000 loading is very slow. How to solve it? How to locate slow SQL?
- 0704、ansible----01
- Pyqt5 and communication
- The central control learning infrared remote control module supports network and serial port control
猜你喜欢
0704、ansible----01
论文阅读《Integrity Monitoring Techniques for Vision Navigation Systems》——3背景
Windows安装redis并将redis设置成服务开机自启
杰理之更准确地确定异常地址【篇】
MapReduce核心和基础Demo
ABAP 7.4 SQL Window Expression
Alibaba cloud architects interpret the four mainstream game architectures
Career planning and implementation in the era of meta universe
NEC infrared remote control coding description
面试官:说几个PHP常用函数,幸好我面试之前看到了这篇文章
随机推荐
Rain produces hundreds of valleys, and all things grow
论文阅读《Integrity Monitoring Techniques for Vision Navigation Systems》——5结果
ABAP 7.4 SQL Window Expression
从知识传播的维度对比分析元宇宙
Easy to understand subset DP
SAP debug debug for in, reduce and other complex statements
解决VMware卸载后再安装出现的问题
Practice of Flink streaming batch integration in Xiaomi
2022年上海市安全员C证考试题库及答案
代码源每日一题 div1 (701-707)
计算机网络安全实验二|DNS协议漏洞利用实验
SAP pi / PO function operation status monitoring and inspection
1D / 1D dynamic programming learning summary
(Extended) bsgs and higher order congruence equation
Skill point digging
Nvidia最新三维重建技术Instant-ngp初探
ABAP publishes OData service samples from CDs view
[ACM-ICPC 2018 Shenyang Network preliminaries] J. Ka Chang (block + DFS sequence)
Interviewer: let's talk about some commonly used PHP functions. Fortunately, I saw this article before the interview
第一章 Oracle Database In-Memory 相关概念(IM-1.1)