1

Java の MCS Lock に対して、非常に奇妙なキャッシュ動作が発生します。基本的に、最大 4 つのスレッド (私のマシンのコアの数) で動作しますが、それ以上になるとスタックします。デバッグすると、プログラムが行で動かなくなっていることがわかります

while (qnode.locked);

lock() 関数の内部。デバッグ時に、スレッドの QNode の 1 つがロックされて 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 の値を設定する前に、この値が lock メソッドで true になるまで待つ必要があります。追加した

 
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 に答える