Atomic原子类-3

简介: Atomic原子类-3

@TOC

  • 在Atomic原子类-1 和 Atomic原子类-2
  • 我们介绍了Atomic 的用法以及简单的底层实现,那么我们这片文章讲下Atomic 的累加器

Adder 累加器

  • 是jdk 1.8 中引入的,比较新的一个类
  • 高并发的情况下 LongAdder 比 AtomitLong 效率高,不过是空间换时间
  • 竞争激烈的时候,LongAdder把不同的线程对应到不同的cell上进行修改,降低了冲突的概率,是多段锁的理念,提高了并发性

测试 AtomicLong的 性能

package com.yxzapp.ready;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 演示高并发情况下LongAdder 比 AtomicLong
 * 性能好
 */
public class AtomicLongDemo {

    public static void main(String[] args) throws InterruptedException {
        AtomicLong atomicLong = new AtomicLong(0);
        //线程池开始时间
        long start = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        for (int i = 0; i < 10000; i++) {
            executorService.submit(new Task(atomicLong));
        }
        //表示线程池执行完毕
        executorService.shutdown();
        while (!executorService.isTerminated()){

        }
        long end = System.currentTimeMillis();
        System.out.println(atomicLong.get());
        System.out.println("耗时"+(end -start));
    }


    public static class Task implements Runnable{

        private AtomicLong atomicLong;

        public Task(AtomicLong atomicLong) {
            this.atomicLong = atomicLong;
        }

        @Override
        public void run() {

            for (int i = 0; i < 10000; i++) {
                atomicLong.incrementAndGet();
            }
        }
    }
}

运行结果:
在这里插入图片描述


package com.yxzapp.ready;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * 演示高并发情况下LongAdder 比 AtomicLong
 * 性能好
 */
public class LongAdderDemo {

    public static void main(String[] args) throws InterruptedException {
        LongAdder atomicLong = new LongAdder();
        //线程池开始时间
        long start = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        for (int i = 0; i < 10000; i++) {
            executorService.submit(new Task(atomicLong));
        }
        //表示线程池执行完毕
        executorService.shutdown();
        while (!executorService.isTerminated()){

        }
        long end = System.currentTimeMillis();
        System.out.println(atomicLong.sum() );
        System.out.println("耗时"+(end -start));
    }


    public static class Task implements Runnable{

        private LongAdder longAdder;

        public Task(LongAdder longAdder) {
            this.longAdder = longAdder;
        }

        @Override
        public void run() {

            for (int i = 0; i < 10000; i++) {
                longAdder.increment();
            }
        }
    }
}
在这里插入代码片

运行结果
在这里插入图片描述
会发现Longadder 比 AtomicLong 快了好多

  • 他们内部实现有些不同,AtomicLong每次加法都需要同步,所以冲突的比较多,也就降低了效率
  • 而 Longadder,每个线程都有自己的计数器,仅用来线程内计数,不会和其他线程干扰
  • AtomicLong引入了分段锁的概念,内部有一个base变量 和 cell[] 数组共同参与计数
  • base变量:竞争不激烈,直接累加到该变量上
  • cell [] 数组: 竞争激烈,各个线程分累加到自己到cell[i] 卡槽中

Accumulator 累加器

  • Accumualtor 和 Adder 非常相似,Accumualtor就是更通用的版本Adder
package com.yxzapp.ready;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.stream.IntStream;

public class LongAccumulatorDemo {

    public static void main(String[] args) {
        LongAccumulator accumulator = new LongAccumulator((x,y)->x+y,0);
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        IntStream.range(1,10).forEach(i->executorService.submit(()->accumulator.accumulate(i)));
        executorService.shutdown();
        while (!executorService.isTerminated())
        System.out.println(accumulator.getThenReset());
    }

    public class Task{
        private LongAccumulator accumulator;

        public Task(LongAccumulator accumulator) {
            this.accumulator = accumulator;
        }
    }
}

对比
在这里插入图片描述

相关文章
|
SQL 缓存 安全
JUC第十讲:CAS,Unsafe和原子类详解
JUC第十讲:CAS,Unsafe和原子类详解
JUC第十讲:CAS,Unsafe和原子类详解
|
5月前
|
安全 前端开发 Java
并发编程之原子操作Atomic&Unsafe
并发编程之原子操作Atomic&Unsafe
|
2月前
|
存储 安全 C++
C++ 原子变量atomic variable
原子变量是 C++11 引入的一种同步机制,用于多线程环境中的无锁、线程安全操作。其操作不可分割,避免了数据竞争和不一致问题。原子变量位于 `&lt;atomic&gt;` 头文件中,支持多种类型如 `std::atomic&lt;T&gt;` 和特化类型。基本用法包括定义原子变量、加载、存储、交换及比较交换操作。内存顺序(如 `std::memory_order_seq_cst`)用于控制内存访问顺序和可见性,适用于不同场景。原子变量常用于线程安全的计数器和标志位等。
|
3月前
|
安全 Java API
Java多线程编程:使用Atomic类实现原子操作
在Java多线程环境中,共享资源的并发访问可能导致数据不一致。传统的同步机制如`synchronized`关键字或显式锁虽能保障数据一致性,但在高并发场景下可能导致线程阻塞和性能下降。为此,Java提供了`java.util.concurrent.atomic`包下的原子类,利用底层硬件的原子操作确保变量更新的原子性,实现无锁线程安全。
32 0
|
6月前
|
安全 Java vr&ar
Atomic原子类总结
Atomic原子类总结
|
安全 Java
【JUC基础】10. Atomic原子类
Atomic英译为原子的。原子结构通常称为不可分割的最小单位。而在JUC中,java.util.concurrent.atomic 包是 Java 并发库中的一个包,提供了原子操作的支持。它包含了一些原子类,用于在多线程环境下进行线程安全的原子操作。使用原子类可以避免使用锁和同步机制,从而减少了线程竞争和死锁的风险,并提高了多线程程序的性能和可伸缩性。
123 0
并发编程(八)Unsafe&Atomic
并发编程(八)Unsafe&Atomic
81 0
|
算法 安全 Java
【小家java】原子操作你还在用Synchronized?Atomic、LongAdder你真有必要了解一下了(上)
【小家java】原子操作你还在用Synchronized?Atomic、LongAdder你真有必要了解一下了(上)
【小家java】原子操作你还在用Synchronized?Atomic、LongAdder你真有必要了解一下了(上)