Я написал простую программу для проверки пропускной способности блокировки CLH. У меня есть код, как описано в книге «Искусство многоядерного программирования». Затем я запустил счетчик на изменение количества потоков в течение 10 секунд и определил счетчик/10.0 в качестве пропускной способности.Масштабируемость и ограничения SpinLock
Вопрос заключается в том, находятся ли результаты, которые я получил, в пределах логического диапазона и какова может быть причина, по которой они такие, как они. Я спрашиваю, потому что падение пропускной способности для блокировки CLH происходит очень быстро. Это результаты для блокировки cLH, где слева указано количество потоков, а справа - пропускная способность (размер счетчика, приходящийся на каждый поток, увеличивающий его один раз в критическом разделе, защищенном блокировкой CLH, деленный на 10).
CLH 1 2.89563825E7 2 1.33501436E7 4 5675832.3 8 15868.9 16 11114.4 32 68.4
Как вы видите безумие оставит машину и заставляет меня думать, что я, возможно, испортил что-то еще до.
Это мой код блокировки CLH (так же, как и в упомянутой выше книге):
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);
}
}
Прогон состоит из главного потока в ожидании в течение 10 секунд в то время как другие пытаются заблокировать, прирост , а затем разблокировать до тех пор, пока нестабильное логическое сообщение не сообщит им, что время завершено.
В моем опыте большая деградация вызвана cpu hogging во вращении. 'while (pred.locked.get()) {}', вероятно, может быть более общительным с 'while (pred.locked.get()) {Thread.yield();}'. Не имеет значения, так что только комментирование. – OldCurmudgeon