当前位置:   article > 正文

JUC 原子操作封装类_juc封装

juc封装

1 什么是 JUC 原子操作封装类

  • 原子操作封装类是 JUCA(java.util.concurrent.atomic)包下的类的总称
  • 都是基于 CAS(compare and swap) 实现的
  • 它可以将单个变量赋值操作封装成原子性操作

2 JUCA 的应用场景

  • 多线程下,不使用,实现单个变量赋值操作

3 锁与 JUCA 的选择问题

  • 极其高的并发下,可能有许多线程一直做循环 CAS,导致 CPU 无效使用率太高,进一步导致赋值操作效率越来越低
    • 一个线程设置完,其它线程如果都读取到旧值,后面争取 CPU 和比较操作都是无意义的消耗,并且一个线程可能有好多次的这种无意义的消耗
    • 而如果使用锁,就不存在读取旧值、比较操作的 CPU 消耗,只有加锁/释放锁的消耗,并且只有固定次数的锁消耗
  • 上面说的极其高也没有一个具体的说法,并且随着 synchornized 锁的不断优化,原生锁的性能也会越来越高
  • 只是 JUCA 包下的类使用会更简洁,并不一定性能就高
  • 具体场景可以综合测试最后做出选择,一般没必要纠结,最赋值操作就简单的选择 JUCA

4 为什么使用 JUCA

  • 提供了多线程单个变量赋值原子性操作
  • 使用简单

5 JUCA 源码分析

5.1 原子操作类总纲

在这里插入图片描述

5.2 Atomic 类
  • Atomic 类有三种子类,分别代表原子更新的布尔类型、整型、长整型
  • AtomicBoolean 方法解析:6个方法
    • 内部通过 volatile int value 属性的 CAS 操作实现原子性操作
    • 可见 Boolean 属性最终转换为 int 属性来处理了
AtomicBoolean ab = new AtomicBoolean(true);

ab.compareAndSet(true,false);		//比较然后赋值,如果旧值为 true,就设置为 false,设置成功才返回 true,否则返回 false,单个 CAS 就结束
ab.weakCompareAndSet(true,false);	//目前和 compareAndSet 方法一模一样
ab.get();			   			  //获取最新的值(因为有 volatile 修饰)

ab.getAndSet(true);		//循环 CAS 获取最新的值,并赋为 true
ab.lazySet(false);		//内部调用unsafe.putOrderedInt() 方法,这个是普通的设置int,值未必立刻回写到主存
ab.set(true);			//立即set,因为内部的 value 属性被 volatile 修饰
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • AtomicInteger 方法解析:16个方法
    • 内部通过 volatile int value 属性的 CAS 操作实现原子性操作
    • 相比AtomicBoolean类,多了很多赋值方法
AtomicInteger ai = new AtomicInteger(0);

ai.getAndIncrement();		//获取旧值,并加1,内部 CAS 循环加1,直到成功
ai.incrementAndGet();		//加1,并获取新值,内部 CAS 循环加1,直到成功

ai.getAndDecrement();		//获取旧值,并减1,内部 CAS 循环减1,直到成功
ai.decrementAndGet();		//减1,并获取新值,内部 CAS 循环减1,直到成功

ai.getAndAdd(2);		    //获取旧值,并加2,内部 CAS 循环加2,直到成功
ai.addAndGet(2);		    //加2,并获取新值,内部 CAS 循环加2,直到成功

ai.getAndAccumulate(6,Math::max);	//循环 CAS 设置 二元运算后的值。二值运算的第一位是获取到的最新值,第二位是设置的值(6)
ai.accumulateAndGet(4,(x,y)->{
   	    //和上面的区别只是,最后返回的值是 二元运算后的值
    return x+y;
});

ai.getAndUpdate(Math::abs);			//循环 CAS 设置 一元运算后的值,获取的是旧值
ai.updateAndGet((x)->{
   			    //循环 CAS 设置 一元运算后的值,获取的是新值
    return x*x;
});

ai.get();					    //获取最新的值(因为有 volatile 修饰)
ai.getAndSet(2);			     //循环 CAS 获取最新的值,并设置属性为2

ai.set(3);						//设置属性为2
ai.compareAndSet(1,2);		 	 //如果属性为1,则设置为2。成功返回 true。否则返回 false
ai.lazySet(3);					//ab.lazySet(false)
ai.weakCompareAndSet(3,3);		 //目前和 compareAndSet() 方法一样
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • AtomicLong 方法解析:和 AtomicInteger 方法一模一样,只是 value 的属性从 int 变成了 long
5.3 AtomicArray 类
  • 实现数组中元素的原子性更新操作

  • AtomicArray 类内部维护一个 final 修饰的 array 数组

    • array 数组并没有被 volatile 修饰
    • 即使数组被 volatile 修饰,只是数组的引用可见,数组的内部元素并不可见
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/48513
推荐阅读
相关标签
  

闽ICP备14008679号