JUC:原子操作类

4.7 原子操作类

4.7.1 基本类型原子类

  • AtomicInteger
  • AtomicBoolean
  • AtomicLong

常用API:

  • get()
  • getAndSet(int newValue)
  • getAndIncrement();
  • getAndDecrement();
  • getAndAdd(int delta)
  • compareAndSet(int expect, int newValue);

4.7.2 数组类型原子类

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray

常用API

  • get(int index)
  • getAndSet(int index, int newValue)

4.7.3 引用类型原子类

  • AtomicReference
  • AtomicStampedReference: 带版本号:+1
  • AtomicMarkableReference:带标识:是否被修改过:false -> true。一次性数据

4.7.4 对象的属性修改原子类

  • AtomicIntegerFieldUpdater

  • AtomicLongFieldUpdater

  • AtomicReferenceFieldUpdater

  • 使用目的:以一种线程安全的方式修改非线程安全对象内的某些字段

  • 使用要求:

    • 更新的属性必须使用public volatile修饰
    • 对象的属性修改原子类都是抽象类,使用时必须使用静态方法newUpdater()创建一个更新器
public class AtomicTest {
    public static void main(String[] args) {
        Student tom = new Student("Tom", 23);
        System.out.println(tom);
        AtomicIntegerFieldUpdater<Student> updater = AtomicIntegerFieldUpdater.newUpdater(Student.class, "age"); // 使用静态方法创建
        updater.compareAndSet(tom, 23, 18);
        System.out.println(tom);
    }
}


@Data
@AllArgsConstructor
class Student{
    private String name;
    public volatile int age; // 使用public volatile 修饰
}

4.7.5 原子操作增强类原理深度解析

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder : 如果是Java8,推荐使用LongAdder,比AtomicLong性能高(减少乐观锁重试次数)

点赞计数器:看看性能

public class AtomicTest {
    public static void main(String[] args) throws InterruptedException {

        int _1W = 100000;
        int threadNum = 50;
        CountDownLatch countDownLatch1 = new CountDownLatch(threadNum);
        CountDownLatch countDownLatch2 = new CountDownLatch(threadNum);
        CountDownLatch countDownLatch3 = new CountDownLatch(threadNum);


        ClickNumber clickNumber = new ClickNumber();
        long start = System.currentTimeMillis();

        for(int i = 0; i < threadNum; i++) {
            new Thread(()->{
                try{
                    for(int j = 0; j < _1W * 100; j++) {
                        clickNumber.clickByLongAdder();
                    }
                }finally {
                    countDownLatch1.countDown();
                }

            }).start();
        }

        countDownLatch1.await();
        long end = System.currentTimeMillis();
        System.out.println( clickNumber.getLongAdder() + "LongAdder Time: "  + (end - start));

        start = System.currentTimeMillis();
        for(int i = 0; i < threadNum; i++) {
            new Thread(()->{
                try {
                    for(int j = 0; j < _1W * 100; j++) {
                        clickNumber.clickByAtomicLong();
                    }
                }finally {
                    countDownLatch2.countDown();
                }

            }).start();
        }
        countDownLatch2.await();
        end = System.currentTimeMillis();
        System.out.println( clickNumber.getAtomicLong() +  "AtomicLong Time: " + (end - start));

        start = System.currentTimeMillis();
        for(int i = 0; i < threadNum; i++) {
            new Thread(()->{
                try {
                    for(int j = 0; j < _1W * 100; j++) {
                        clickNumber.clickByLongAccumulator();
                    }
                }finally {
                    countDownLatch3.countDown();
                }

            }).start();
        }
        countDownLatch3.await();
        end = System.currentTimeMillis();
        System.out.println( clickNumber.getLongAccumulator() + "LongAccumulator Time: " + (end - start));
    }
}

@Data
class ClickNumber{
    AtomicLong atomicLong = new AtomicLong(0);
    public void clickByAtomicLong(){
        atomicLong.getAndIncrement();
    }

    LongAdder longAdder = new LongAdder();
    public void clickByLongAdder(){
        longAdder.increment();
    }

    LongAccumulator longAccumulator = new LongAccumulator(Long::sum, 0L);
    public void clickByLongAccumulator(){
        longAccumulator.accumulate(1);
    }
}
500000000LongAdder Time: 209
500000000AtomicLong Time: 4241
500000000LongAccumulator Time: 205

Process finished with exit code 0

  • 原理分析
    • base变量: 低并发,直接累加到该变量上
    • Cell[]数组: 高并发,累加进各个线程自己的Cell[i]槽位中
      • value = base + sum(Cell[i])
    • 空间换时间,分散热点数据,减少乐观锁的重试次数
posted @ 2025-09-30 12:25  飞↑  阅读(3)  评论(0)    收藏  举报