多处理器编程 - badclhlock

时间:2013-12-29 14:21:12

标签: multiprocessing

此代码实现了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;
}

}

2 个答案:

答案 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为两个并发线程。
  • 让QN1,QN2分别为每个线程的QNode。

死锁场景:

  1. T1和T2从未获得锁定:

    Tail -> Null
    
  2. T1获取锁

    Tail -> QN1(true)
    
  3. T2尝试获取锁定,但因为T1有,所以必须等待

    Tail -> QN2(true) -> QN1(true)
    
  4. T1释放锁

    Tail -> QN2(true) -> QN1(false)
    
  5. 但之前,T2检查QN1已经释放锁定,T1尝试重新获取它。

    Tail -> QN1(true) -> QN2(true) -> QN1(true)
    
  6. 因为QN2指向QN1作为其前身,而QN1一无所知。 QN2认为QN1仍然保持锁定,而QN1必须等待QN2释放它。

  7. 发生死锁情况,没有人能够获得锁定。