Ich habe ein einfaches Programm geschrieben, um den Durchsatz des CLH-Lock zu testen. Ich habe den Code wie in "Die Kunst der Multicore-Programmierung" beschrieben. Als nächstes habe ich einen Zähler auf eine sich ändernde Anzahl von Threads für 10 Sekunden laufen lassen und den Zähler/10.0 als Durchsatz definiert.SpinLock Skalierbarkeit und Einschränkungen
Meine Frage ist, ob die Ergebnisse, die ich bekommen habe, im logischen Bereich liegen und was der Grund dafür sein könnte, dass sie so sind wie sie sind. Ich frage, weil der Durchsatzabfall für das CLH-Lock extrem schnell ist. Dies sind die Ergebnisse für die cLH-Sperre, wobei links die Anzahl der Threads und rechts der Durchsatz angibt (die Größe des Zählers wurde mit jedem Thread erhöht, einmal in dem durch die CLH-Sperre geschützten kritischen Abschnitt, geteilt durch 10).
CLH 1 2.89563825E7 2 1.33501436E7 4 5675832.3 8 15868.9 16 11114.4 32 68.4
Wie Sie sehen die Drop-Off-verrückt ist und lässt mich denken, dass ich etwas anderes durcheinander haben.
Dies ist mein Code für die CLH Sperre (so wie es in dem oben erwähnten Buch ist):
static class CLHLock implements Lock {
AtomicReference<QNode> tail;
ThreadLocal<QNode> myNode, myPred;
public CLHLock() {
tail = new AtomicReference<QNode>(new QNode());
this.myNode = new ThreadLocal<QNode>() {
protected QNode initialValue() {
return new QNode();
}
};
this.myPred = new ThreadLocal<QNode>() {
protected QNode initialValue() {
return null;
}
};
}
public void lock() {
QNode qnode = this.myNode.get();
qnode.locked.set(true);
QNode pred = this.tail.getAndSet(qnode);
myPred.set(pred);
while (pred.locked.get()) {}
}
public void unlock() {
QNode qnode = this.myNode.get();
qnode.locked.set(false);
this.myNode.set(this.myPred.get());
}
static class QNode {
public AtomicBoolean locked = new AtomicBoolean(false);
}
}
Der Lauf des Hauptthread 10 Sekunden lang warten, besteht, während die andere zu sperren versuchen, erhöht und entsperren, bis ein flüchtiger Boolescher Wert besagt, dass die Zeit abgelaufen ist.
Meiner Erfahrung nach wird die meiste Degradierung durch CPU-Chogging im Spin verursacht. 'while (pred.locked.get()) {}' könnte wahrscheinlich geselliger sein mit 'while (pred.locked.get()) {Thread.yield();}'. Kann keinen Unterschied machen, also nur kommentieren. – OldCurmudgeon