AtomicLongよりLongAdder使ったほうが良いみたいなはなしの理解
AtomicLongを使っていた箇所でLongAdder使ったほうが良いよという話が出てきたんだけど、なんでそっちのほうがよくわかってなかったのでメモ
AtomicLongとかだとあんま良くないケースについて
AtomcLongとかはCASって操作を行うように実装されており、それが高速なforループの中とかで使われているとパフォーマンスに影響が出るよというはなしらしい
ではCASとはどのような操作なのか?
疑似コードだと以下のようなイメージ
code: java
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
この処理自体はアトミックになっていて、スレッドごとに不整合は起きないようになっているが、compreAndSetには複数のスレッドがアクセスする可能性がある
compareAndSetは処理が成功するとTrueが返るけど、複数のスレッドが同時に成功することはない
成功しなかったスレッドはループを回して再トライすることになるので、整合性は保ちつつIncrementを進めることができる
Now because of atomics - only one thread will succeed, the other will recieve false from the compareAndSet and go around again.
The atomicity guarantees that the new value is calculated based on up-to-date information; if the value had been updated by another thread in the meantime, the write would fail.
以上のようにあるスレッドでCAS操作が失敗した場合は再トライする作りのため、高速なループのなかで複数のスレッドからインクリメントすると、競合が多く発生し、再トライの回数が増えて効率性が落ちるよという話だと理解した。
LongAdderだとどうして効率が良いのか?
Each Cell in a LongAdder is a variant of an AtomicLong. Having multiple such cells is a way of spreading out the contention and thus increasing throughput.
When the final result (sum) is to be retrieved, it just adds together the values of each cell.
どうやら LongAdderは内部的にAtomicLong的なオブジェクトを複数持っており、それらを並行的に動かし、最後に足し合わせることで競合を避けながらパフォーマンスを上げているよという話のようだった
内部的なAtomicLong的なオブジェクトはCPU的の数だけ生成されて効率的に処理されるようになっている!!!!