AQS 中获取公平锁的代码如下( jdk1.8 ): 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(),都判断出为 false(此时队列为空,他们都可以获取锁),第二个线程继续走(第三个线程时间片到了,停住),获取锁失败(因为锁已经被第一个线程获取了),那就乖乖的去排队,构造头结点与自己的节点,此时 sync 队列为: head → node2,node2 → head,然后第二个线程又来抢占锁(源码中有个 for 循环),走到 hasQueuedPredecessors(),判断出也为 false (因为自己就是队列中的第二个节点,是有资格抢锁的),此时线程一释放了锁,那么第二个线程与第三个线程同时抢锁,锁是有可能被三个线程抢到了。
那么这是不是违背了公平锁的概念,或者公平锁并不是绝对的公平,因为第二个线程已经在队列里面排好了队,也该是自己拿到锁,结果锁被第三个线程拿走了。
麻烦各位大神解惑一下!!!
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.