Я написал простую программу для проверки пропускной способности блокировки CLH. У меня есть код, как описано в книге "Искусство многоядерного программирования". Затем я запустил счетчик изменяющегося количества потоков на 10 секунд и определил counter/10.0 как пропускную способность.
Мой вопрос заключается в том, находятся ли результаты, которые я получил, в пределах логического диапазона и что может быть причиной того, что они такие, какие они есть. Я спрашиваю, потому что падение пропускной способности для блокировки 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 секунд, в то время как другие пытаются заблокировать, увеличить, а затем разблокировать, пока изменчивое логическое значение не сообщит им, что время истекло.
while (pred.locked.get()) {}
мог бы быть более общительным сwhile (pred.locked.get()) {Thread.yield();}
. Может без разницы, так что только комментировать. - person OldCurmudgeon   schedule 11.05.2016