1

对于 Java 中的 MCS Lock,我得到了一些非常奇怪的缓存行为。基本上,它最多可用于四个线程(我机器上的内核数),但会卡住更多。当我调试时,我看到程序卡在了线上

while (qnode.locked);

在 lock() 函数内部。调试时,我可以看到其中一个线程的 QNode 已锁定设置为 false,但我猜这是因为调试器导致缓存更新。我只是将“易失性”扔到所有变量上,绝望地尝试无济于事。这是我正在使用的课程:

class MCSLock
{
private volatile AtomicReference<QNode> tail;
private volatile ThreadLocal<QNode> myNode;

public MCSLock()
{
    tail = new AtomicReference<QNode>(null);
    myNode = new ThreadLocal<QNode>()
            {
                protected QNode initialValue() { return new QNode(); }
            };
}

public void lock()
{
    QNode qnode = myNode.get();
    QNode pred = tail.getAndSet(qnode);
    if (pred != null)
    {
        qnode.locked = true;
        pred.next = qnode;
        while (qnode.locked);
    }
}

public void unlock()
{
    QNode qnode = myNode.get();
    if (qnode.next == null)
    {
        if (tail.compareAndSet(qnode, null)) return;
        while (qnode.next == null);
    }
    qnode.next.locked = false;
    qnode.next = null;
}

private class QNode
{
    volatile boolean locked = false;
    volatile QNode next = null;
}
}
4

3 回答 3

1

我有同样的问题。unlock() 方法有一个小错误。在将 false 值设置为下一个节点的锁定变量之前,我们需要等到该值变为 true 才能进入 lock 方法。我添加了

 
while (!qnode.next.locked) {}
    

    qnode.next.locked = false;
    
进入 unlock() 方法,问题就跑了!

于 2015-12-23T15:08:06.337 回答
0

while (qnode.locked);据我所知,没有做任何事情。也许你的意思是

    do {
        pred.next = qnode;
        // update qnode
       } while (qnode.locked);
于 2012-10-30T17:04:40.057 回答
0

您的代码有效!但是,我的猜测是您的系统不足以快速执行 >4 个线程。

在双核 i5 上运行,执行挂在 5 个线程上

在四核超频 i7 上运行,按预期在 5 个线程上完成。哇!

于 2012-10-30T22:05:36.627 回答