线程安全之原子操作

本文主要内容

1、原子操作定义

2、原子操作的方式(同步锁机制、cas机制、原子操作类)

3、总结


一、原子操作定义

    1、定义:

     原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而执行其中的一部分,原子操作具有不可中断性。它的核心特征是将整个操作视为一个整体。

    2、实例:        

     上面的截图中i++操作存在多个操作,在多线程环境下会出现竞态条件,线程不安全,需要转变为原子操作才能安全。下面将介绍操作操作的方式。


二、原子操作方式

      1、同步锁机制:

   2、cas机制

     定义:cas机制:cas操作需要输入两个数值,一个旧值A和一个新值B,在操作期间先比较下旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。

  java中sun。misc。Unsafe类提供了一些方法实现cas。

    实例:

     

   3、原子操作封装类

    (1)基础版: Java中提供了一些原子操作封装类,封装了cas机制的底层代码,使得用户使用起来更加方便。

     例如:

      AtomicBoolean:原子更新布尔类型;AtomicInteger:原子更新整型;AtomicLong:原子更新长长整型。

     AtomicIntegerArray:原子更新整型数组里的元素。 AtomicLongArray:原子更新长整型数组里的元  素。         AtomicReferenceArray:原子更新引用数组里的元素。

    AtomicIntegerFieldUpdater:原子更新整型字段里的更新器。    AtomicLongFieldUpdater:原子更新长整型字段里的更新器。    AtomicReferenceFieldUpdater:原子更新引用类型里的字段。

    AtomicReference:原子更新引用类型。    AtomicStampedReference:原子更新带有版本号的引用类型。    AtomicMarkableReference:原子更新带有标记位的引用类型。

   实例:下面介绍AtomicInteger类的实例

    


    (2)更新版: 1.8版本的jdk还更新了四个原子操作的封装类。

      更新器:DoubleAccumulator、LongAccumulator

      计数器:DoubleAdder、LongAdder

      实例1:介绍LongAccumulator类使用代码    

实例2:下面是LongAdder类的使用代码

计数器增强版,高并发下性能更好,频繁更新但不太频繁读取的汇总统计信息时使用,分成多个操作单元,不同线程更新不同的单元,只有需要汇总的时候才计算所有单元的操作


三、总结

cas的弊端:
1、cpu开销大,在高并发下,许多线程,更新一变量,多次更新不成功,循环反复,给cpu带来大量压力。

2、只是一个变量的原子性操作,不能保证代码块的原子性。

3、ABA问题

ABA问题:内存值V=100;

threadA 将100,改为50;

threadB 将100,改为50;

threadC 将50,改为100;

场景:小牛取款,由于机器不太好使,多点了几次全款操作。后台threadA和threadB工作,

此时threadA操作成功(100->50),threadB阻塞。正好牛妈打款50元给小牛(50->100),

threadC执行成功,之后threadB运行了,又改为(100->50)。

牛气冲天,lz钱哪去了???

如何解决aba问题:

对内存中的值加个版本号,在比较的时候除了比较值还的比较版本号。

java:AtomicStampedReference就是用版本号实现cas机制。





    

你可能感兴趣的:(线程安全之原子操作)