2
這不是關於LongAdder如何工作的問題,而是關於一個有趣的實現細節,我無法弄清楚。LongAdder Striped64 wasUncontended實現細節
下面是從Striped64代碼(我剪了一些零部件,並放置問題的相關部分):
final void longAccumulate(long x, LongBinaryOperator fn,
boolean wasUncontended) {
int h;
if ((h = getProbe()) == 0) {
ThreadLocalRandom.current(); // force initialization
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
//logic to insert the Cell in the array
}
// CAS already known to fail
else if (!wasUncontended) {
wasUncontended = true; // Continue after rehash
}
else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))){
break;
}
很多從代碼事情是很清楚,我,除了:
// CAS already known to fail
else if (!wasUncontended) {
wasUncontended = true; // Continue after rehash
}
從哪裏可以確定下面的CAS會失敗?至少這對我來說是很讓人困惑的,因爲這個檢查只對一個案例有意義:當某個線程第n次進入longAccumulate方法(n> 1)並且繁忙的旋轉處於第一個循環時。
就像這段代碼所說的:如果你(某個線程)之前已經在這裏,並且你在特定Cell插槽上有一些爭用,請不要試圖將CAS值賦給已經存在的值,而是重新刷新探測。
我真的希望我會對某人有所幫助。
1)我知道這是從哪裏來的,但thx添加它的方式。 2)該死!我認爲* CAS已知失敗*意味着下一個CAS操作將失敗,而不是前一個。我很喜歡你的猜測,他們可能有測試證明這是對代碼的最佳補充。非常感謝您的意見。 – Eugene
是的,我現在對你的理論有99%的把握(再次查看代碼後)。對我而言,這是違反直覺的,但是對於維護該代碼的人來說,這可能會使事例變得有意義。再一次,謝謝你,我會接受這一點。 – Eugene
是的,這是最明智的解釋。嘗試使用CAS在某個時間遞增整數的緊湊競爭循環。在激烈的爭論中,你可以很容易地擁有90 +%不成功的CAS。 – Voo