LongAdder的属性

  1. // 累加单元数组, 懒惰初始化
  2. transient volatile Cell[] cells;
  3. // 基础值, 如果没有竞争, 则用 cas 累加这个域
  4. transient volatile long base;
  5. // 在 cells 创建或扩容时, 置为 1, 表示加锁
  6. transient volatile int cellsBusy;

Cell 累加单元

  1. // 防止缓存行伪共享
  2. @sun.misc.Contended
  3. static final class Cell {
  4. volatile long value;
  5. Cell(long x) { value = x; }
  6. // 最重要的方法, 用来 cas 方式进行累加, prev 表示旧值, next 表示新值
  7. final boolean cas(long prev, long next) {
  8. return UNSAFE.compareAndSwapLong(this, valueOffset, prev, next);
  9. }
  10. // 省略不重要代码
  11. }

AtomicLong与LongAdder性能对比

  1. public class Test41 {
  2. public static void main(String[] args) {
  3. for (int i = 0; i < 5; i++) {
  4. demo(
  5. () -> new AtomicLong(0),
  6. (adder) -> adder.getAndIncrement()
  7. );
  8. }
  9. for (int i = 0; i < 5; i++) {
  10. demo(
  11. () -> new LongAdder(),
  12. adder -> adder.increment()
  13. );
  14. }
  15. }
  16. /*
  17. () -> 结果 提供累加器对象
  18. (参数) -> 执行累加操作
  19. */
  20. private static <T> void demo(Supplier<T> adderSupplier, Consumer<T> action) {
  21. T adder = adderSupplier.get();
  22. List<Thread> ts = new ArrayList<>();
  23. // 4 个线程,每人累加 50 万
  24. for (int i = 0; i < 4; i++) {
  25. ts.add(new Thread(() -> {
  26. for (int j = 0; j < 500000; j++) {
  27. action.accept(adder);
  28. }
  29. }));
  30. }
  31. long start = System.nanoTime();
  32. ts.forEach(t -> t.start());
  33. ts.forEach(t -> {
  34. try {
  35. t.join();
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39. });
  40. long end = System.nanoTime();
  41. System.out.println(adder + " cost:" + (end - start) / 1000_000);
  42. }
  43. }

image.png