此代码实现了CLHLock的替代实现 线程重用其自己的节点而不是其前任节点。怎么样 实施可能出错?
public class BadCLHLock implements Lock {
// most recent lock holder
AtomicReference<Qnode> tail;
// thread-local variable
ThreadLocal<Qnode> myNode;
public void lock() {
Qnode qnode = myNode.get();
qnode.locked = true;
// I’m not done
// Make me the new tail, and find my predecessor
Qnode pred = tail.getAndSet(qnode);
// spin while predecessor holds lock
while (pred.locked) {}
}
public void unlock() {
// reuse my node next time
myNode.get().locked = false;
}
static class Qnode { // Queue node inner class
public boolean locked = false;
}
}
答案 0 :(得分:1)
如果线程A运行lock(),则解锁()然后再次锁定() 什么时候
Qnode pred = tail.getAndSet(qnode);
执行qnode并且pred将引用相同的节点,因此 pred.locked永远是真的。
所以,如果myNode = A从头开始,在第一次锁定后() 还有tail = A.现在当我们再次运行lock()时,我们首先设置 A.locked = true,设置pred = tail(pred = A)并等待A.locked变为true,这将不会发生。
- 这是Herlihy&amp; Sons的“多处理器编程艺术”中的练习85。沙维特
答案 1 :(得分:1)
死锁场景:
T1和T2从未获得锁定:
Tail -> Null
T1获取锁
Tail -> QN1(true)
T2尝试获取锁定,但因为T1有,所以必须等待
Tail -> QN2(true) -> QN1(true)
T1释放锁
Tail -> QN2(true) -> QN1(false)
但之前,T2检查QN1已经释放锁定,T1尝试重新获取它。
Tail -> QN1(true) -> QN2(true) -> QN1(true)
因为QN2指向QN1作为其前身,而QN1一无所知。 QN2认为QN1仍然保持锁定,而QN1必须等待QN2释放它。
发生死锁情况,没有人能够获得锁定。