【发布时间】:2016-09-06 14:44:44
【问题描述】:
我编写了一个简单的程序来测试 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 秒的主线程,而其他线程尝试锁定、递增,然后解锁,直到一个 volatile 布尔值告诉他们时间到了。
【问题讨论】:
-
根据我的经验,大多数性能下降是由 CPU 占用过多造成的。
while (pred.locked.get()) {}可能与while (pred.locked.get()) {Thread.yield();}更友好。可能没有区别,所以只能评论。
标签: java multithreading locking throughput spinlock