JUC之Atomic

这个是在学习工作中的一些总结,若有不对之处欢迎大家指出。侵删!
需要源码联系QQ:1352057131
得之在俄顷,积之在平日。

原子类的作用

原子类和锁的作用类似,都是为了保证并发情况下的线程安全,不过原子类相比于锁有一定的优势:

粒度更细:原子变量可以把竞争范围缩小到变量级别。
效率更高:使用原子类的效率比使用锁的效率更高,但是高竞争下的情况除外。

原子类概览

在这里插入图片描述

Atomic*基本类型原子类

AtomicInteger常用方法

//获取当前的值并加上预期的值
atomicInteger.getAndAdd(int value);
//获取当前值
atomicInteger.get();
//获取当前值并自减
atomicInteger.getAndDecrement();
//获取当前值并自增
atomicInteger.getAndIncrement();
//获取当前值并设置新值
atomicInteger.getAndSet(int value);
//如果输入的值等于预期值,则以原子的方式将该值设置为输入值(update)
atomicInteger.compareAndSet(int value,int update);

AtomicInteger示例

public class AtomicTest implements Runnable{
    private static  AtomicInteger atomicInteger = new AtomicInteger(0);
    private static int a = 0;
    public static void Atomicadd(){
        atomicInteger.getAndIncrement();
    }
    public static void add(){
        a++;
    }
    public static void main(String[] args) throws InterruptedException {
        Thread thread0 = new Thread(new AtomicTest());
        Thread thread1 = new Thread(new AtomicTest());
        thread0.start();
        thread1.start();
        thread0.join();
        thread1.join();
        System.out.println("atomicInteger="+atomicInteger);
        System.out.println("a="+a);
    }
    @Override
    public void run() {
        for (int i = 0; i <100000 ; i++) {
            Atomicadd();
            add();
        }
    }
}

运行结果:
从图中可以看出AtomicInteger是线程安全的
从图中可以看出AtomicInteger是线程安全的

Atomic*Array数组类型原子类

AtomicIntegerArray示例

public class AtomicTest{
    //声明长度为100的AtomicIntegerArray
    private static AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(100);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        executorService.submit(new Add(atomicIntegerArray));
        executorService.submit(new Dec(atomicIntegerArray));
        Thread.sleep(1000);
        executorService.shutdown();
        for (int i = 0; i <atomicIntegerArray.length() ; i++) {

            if (atomicIntegerArray.get(i)!=0){
                System.out.println("发现不等于0的数");
            }
        }
        System.out.println("执行完毕");
    }
}
class Add implements Runnable{
    private AtomicIntegerArray atomicIntegerArray;

    public Add(AtomicIntegerArray atomicIntegerArray) {
        this.atomicIntegerArray = atomicIntegerArray;
    }
    @Override
    public void run() {
        for (int i = 0; i < atomicIntegerArray.length(); i++) {
            //加1
            atomicIntegerArray.getAndIncrement(i);
        }
    }
}
class Dec implements Runnable{
    private AtomicIntegerArray atomicIntegerArray;

    public Dec(AtomicIntegerArray atomicIntegerArray) {
        this.atomicIntegerArray = atomicIntegerArray;
    }
    @Override
    public void run() {
        for (int i = 0; i < atomicIntegerArray.length(); i++) {
            //减1
            atomicIntegerArray.getAndDecrement(i);
        }
    }
}

Atomic*Reference引用类型原子类

AtomicReference示例
在这里插入图片描述

Atomic*FieldUpdater升级类型原子类

AtomicIntegerFieldUpdater示例

public class AtomicIntegerFieldUpdaterTest implements Runnable{
    //第一个参数为类  第二个参数为要升级的变量名
    AtomicIntegerFieldUpdater<User> aifu = AtomicIntegerFieldUpdater.newUpdater(User.class,"number");
    static User tom = new User();
    static User tony = new User();
    public static void main(String[] args) throws InterruptedException {
        AtomicIntegerFieldUpdaterTest aifut = new AtomicIntegerFieldUpdaterTest();
               for (int i = 0; i < 1000; i++) {
            Thread thread0 = new Thread(aifut);
            Thread thread1 = new Thread(aifut);
            thread0.start();
            thread1.start();
            thread0.join();
            thread1.join();
        }
        System.out.println("tom"+tom.number);
        System.out.println("tony"+tony.number);
    }
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            tom.number++;
            aifu.getAndDecrement(tony);
        }
    }
    static class User{
        volatile int number;//分数
    }
}

Adder累加器

为什么要使用Adder

高并发下LongAdder比AtomicLong效率高,不过本质是空间换时间。
竞争激烈的时候,LongAdder把不同的线程对应到不同的Cell上进行修改,降低了冲突的概率,事多段锁的理念,提高了并发性。

LongAdder示例

public class AdderTest implements Runnable{
    private static LongAdder longAdder = new LongAdder();
    public void Adder_Add(){
        longAdder.increment();
    }
    @Override
    public void run() {
        Adder_Add();
    }
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i <10000 ; i++) {
            executorService.submit(new AdderTest());
        }
        executorService.shutdown();
        while (!executorService.isTerminated()){
        }
        System.out.println(longAdder);
    }

LongAdder与AtomicLong性能对比
LongAdder:

```java
public class AdderTest implements Runnable{
    private static LongAdder longAdder = new LongAdder();
    public void Adder_Add(){
        for (int i = 0; i < 1000; i++) {
            longAdder.increment();
        }
    }
    @Override
    public void run() {
        Adder_Add();
    }
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        long start = System.currentTimeMillis();
        for (int i = 0; i <100000 ; i++) {
            executorService.submit(new AdderTest());
        }
        executorService.shutdown();
        while (!executorService.isTerminated()){
        }
        long end = System.currentTimeMillis();
        System.out.println("执行时间:"+(end-start));
    }
}

在这里插入图片描述

AtomicLong:

public class AtomicLongTest implements Runnable{
    private static AtomicLong atomicLong = new AtomicLong(0);
    @Override
    public void run() {
        for (int i = 0; i <1000 ; i++) {
            atomicLong.getAndIncrement();
        }
    }
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        long start = System.currentTimeMillis();
        for (int i = 0; i <100000 ; i++) {
            executorService.submit(new AtomicLongTest());
        }
        executorService.shutdown();
        while (!executorService.isTerminated()){
        }
        long end = System.currentTimeMillis();
        System.out.println("执行时间:"+(end-start));
    }
}

在这里插入图片描述
从运行结果可以看出LongAdder的效率明显要高很多,原因如下:
AtomicLong每次加法都要flush和refresh导致很耗费资源
在这里插入图片描述
从图中可以看出AtomicLong每次加法都要做同步,在高并发的情况下会导致冲突比较多因此效率下降,而LongAdder每个线程都会有自己的计数器,仅用来在自己线程内计数,这样就不会受到其他线程计数器的干扰。如下图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从图中可以看出,第一个线程的计数器数值,也就是str’,为1的时候,可能线程2的计数器ctr”的数值已经是3了,他们之间并不存在竞争关系,所以在加和的过程中根本不需要同步机制,也不需要flush和refresh。也没有公共的counter来计数。只是到最后sum的时候才会同步将所有的数值累加起来 。
适用场景

适用于统计求和计数的场景,而且LongAdder基本只提供了add方法,AtomicLong还具有cas操作。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值