本文共 2579 字,大约阅读时间需要 8 分钟。
Striped类是LongAdder实现并发控制的核心组件,主要采用了一种独特的缓存机制来解决多线程环境下的竞争问题。类图如下:
package cn.knightzz.atomic;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.atomic.AtomicInteger;/** * @author 王天赐 * @title: Striped64 * @projectName hm-juc-codes * @description: Striped64用于实现LongAdder的并发控制 * @website http://knightzz.cn/ * @github https://github.com/knightzz1998 * @create: 2022-08-08 20:32 */@Slf4j(topic = "Striped64")public class Striped64 { // 累加单元数组, 懒惰初始化 transient volatile Cell[] cells; // 基础值, 如果没有竞争, 则用 cas 累加这个域 transient volatile long base; // 在 cells 创建或扩容时, 置为 1, 表示加锁 transient volatile int cellsBusy; // 可用cpu数量 static final int NCPU = Runtime.getRuntime().availableProcessors();}
Striped64通过将内存划分为多个缓存行,利用每个线程独有的随机探测器(Probe)来分布处理累加请求,避免了传统的锁机制在高并发场景下的性能瓶颈。
Striped64采用了CAS(比较与交换)机制来实现锁。具体实现如下:
public class CasLock { private static AtomicInteger state = new AtomicInteger(0); public static void lock() { while (true) { if (state.compareAndSet(0, 1)) { break; } } } public static void unlock() { state.set(0); }}
Cell类是Striped64的核心单元,主要负责存储累加值并支持原子性更新。其实现如下:
public class Cell { volatile long value; Cell(long x) { value = x; } final boolean cas(long cmp, long val) { return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val); } private static final sun.misc.Unsafe UNSAFE; private static final long valueOffset; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class ak = Cell.class; valueOffset = UNSAFE.objectFieldOffset(ak.getDeclaredField("value")); } catch (Exception e) { throw new Error(e); } }}
Striped64通过将内存划分为多个64字节的缓存行,每个缓存行对应一个Cell对象。这种机制能够显著提升性能,原因如下:
Striped64的累加方法主要包括以下步骤:
Striped64通过以下机制实现了对高并发场景下的性能优化:
Striped64通过创新的缓存与内存管理机制,结合CAS锁和懒初始化策略,实现了对高并发场景下的性能优化。其核心思想在于将内存划分为多个缓存行,每个线程对应一个独特的Cell对象,从而避免了传统锁机制的性能瓶颈。这种设计理念在现代并发控制中具有重要的参考价值。
转载地址:http://jnufk.baihongyu.com/