我为Java中的MCS Lock获得了一些非常奇怪的缓存行为。基本上,它最多可以用于四个线程(我的机器上的核心数量),但会被卡住更多。当我调试时,我发现程序卡在了行上
while (qnode.locked);
lock()函数内部。调试时,我可以看到其中一个线程的QNode已锁定设置为false,但我猜测是因为调试器导致缓存更新。我只是扔了" volatile"所有变量都是绝望的尝试无济于事。这是我正在使用的课程:
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;
}
}
答案 0 :(得分:1)
我遇到了同样的问题。 unlock()方法有一个小错误。在将false值设置为下一个节点的锁定变量之前,我们需要等待,直到这个值变为lock方法。 我补充道
while (!qnode.next.locked) {}
之前
qnode.next.locked = false;
进入unlock()方法,问题就一团糟了!
答案 1 :(得分:0)
while (qnode.locked);
没有做任何事情。也许你的意思是
do {
pred.next = qnode;
// update qnode
} while (qnode.locked);
答案 2 :(得分:0)
您的代码有效!但是,我的猜测是你的系统不够快,可以快速完成4个线程。
在双核i5上运行,执行挂起5个线程
在四核超频i7上运行,按预期在5个线程上完成执行。宇!