美文网首页程序人生Java学习笔记java进阶干货
[Java并发系列] 2.Java中的原子操作类

[Java并发系列] 2.Java中的原子操作类

作者: Xiangdong_She | 来源:发表于2017-10-19 22:02 被阅读32次
1. 原子操作类的作用

当程序更新一个变量时,如果多个线程同时更新该变量,可能会得到期望以外的值。比如i=1, 线程A更新i+1, 同时线程B更新I+1,经过两个线程的操作,最终变量i的值可能不是3,而是2。因为线程A、B拿到的i的值都是1,这就是线程不安全的更新操作。我们可以用synchronized来解决这样的问题,synchronized可以保证多线程之间的同步,以保证多个线程不会同时操作变量i。
但是在JDK1.5开始,就提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了更为简单高效、线程安全的方式来更新一个变量的值。

2. 原子操作类基本分类
  • 原子更新基本类型(3个)
  1. AtomicBoolean 原子更新布尔类型
  2. AtomicInteger 原子更新整型
  3. AtomicLong 原子更新长整型
  • 原子更新数组(3个)
  1. AtomicIntegerArray 原子更新整形数组中的元素
  2. AtomicLongArray 原子更新长整型数组中的元素
  3. AtomicReferenceArray 原子更新引用类型数组中的元素
  • 原子更新引用类型(3个)
  1. AtomicReference 原子更新引用类型
  2. AtomicReferenceFieldUpdater 原子更新引用类型中的字段
  3. AtomicMarkableReference 原子更新带有标记位的引用类型
  • 原子更新字段类(3个)
  1. AtomicIntegerFieldUpdater 原子更新整形字段
  2. AtomicLongFieldUpdater 原子更新长整型字段
  3. AtomicStampedReference 原子更新带有版本号的引用类型
3. CAS方式实现原子操作基本原理

JVM中CAS操作主要是利用了处理器提供的CMPXCHG执行实现。基本的思路就是利用循环进行CAS操作,直到成功为止。CAS主要涉及到三个操作数,内存中的值(V)、旧的预期值(A)、需要修改的新值(B),当且仅当V==A时,才会将V值修改为B值,否则什么都不做,并且通过一个布尔值返回结果。伪代码如下:

//伪代码
boolean compareAndSwap(V,A,B){
    for(;;){
        if(V==A)
            V=B;//替换旧值
    }
}
4. CAS方式产生的问题(3个)
  1. ABA问题: CAS操作时,检查值有没有变化,如果没有变化则更新,但是如果一个值原来是A,中间变成了B,然后又变为A,CAS进行检查时,就会发现它的值没有变化,但是实际上却已经变化了。解决ABA问题,可以在变量前加一个版本号,变量更新时,版本号就加1.
  2. 循环时间长,开销大:CAS采用的是自循的方式进行检查,如果长时间不成功,那么就会给CPU带来非常大的开销。
  3. 只能保证一个共享变量的原子操作:当对一个共享变量进行原子操作时,我们可以采用CAS的方式进行更新,但是如果对多个共享变量进行操作时,CAS就无法保证操作的原子性,那么这个时候就需要用锁来实现。
5. 原子操作类中主要的方法
  • boolean compareAndSet(int expect, int update) ;如果输入的值等于预期值,那么以原子的方式将该值设为输入的值。
  • int addAndGet(int delta);以原子的方式将输入的数值与实例中的值相加,并返回更新之后的值
  • int getAndAdd(int delta); 以原子的方式将输入的数值与实例中的值相加,并返回旧值
  • int getAndSet(int newValue);以原子方式设置为newValue的值,并返回旧值

通过阅读源码,可以发现CAS操作都是使用Unsafe类下的方法进行操作,而Unsafe类只提供了三种CAS方法:

  • compareAndSwapObject(this, valueOffset, expect, update);
  • compareAndSwapLong(this, valueOffset, expect, update);
  • compareAndSwapInt(this, valueOffset, expect, update);
    所以,对于其他类型的原子操作,都是进行类型转换,将其类型转换为这三种类型,然后进行原子操作。如Boolean型的,先转成整整,然后在使用compareAndSwapInt进行操作;所以像char/float/double/short...等都可以按照这种思路实现。

相关文章

  • [Java并发系列] 2.Java中的原子操作类

    1. 原子操作类的作用 当程序更新一个变量时,如果多个线程同时更新该变量,可能会得到期望以外的值。比如i=1, 线...

  • AtomicInteger原理

    AtomicInteger的原理 java的并发原子包里面提供了很多可以进行原子操作的类,比如: AtomicIn...

  • J.U.C-atomic包

    原子操作类介绍 atomic包下为原子操作类。在并发编程中很容易出现并发安全的问题,有一个很简单的例子就是多线程更...

  • Java - 原子操作类

    Java中的12个原子操作类 原子更新基本类型类 AtomicBoolean:原子更新布尔类型 AtomicInt...

  • Java原子类

    1、原子类的分类 原子操作是指一个不可中断的操作。 原子类是指具有原子操作特征的类。 JUC并发包中的原子类都存放...

  • Java并发(七):原子操作类

    一. 原子更新基本类型 AtomicBoolean:原子更新布尔类型。 AtomicInteger:原子更新整型。...

  • (转载)Java并发编程-并发包中的原子操作类(Atomic系列

    原文链接:Java并发编程-无锁CAS与Unsafe类及其并发包Atomic - CSDN博客 通过前面的分析我们...

  • 并发 - Java中13个原子操作类

    四种类型的原子更新操作: Atomic包里的类基本都是使用Unsafe实现的包装类。 原子更新基本数据类型 Ato...

  • Java: AtomicReference 详解

    Java中的AtomicReference是一个原子引用类,用于实现在并发环境下的线程安全的操作,它可以在不使用锁...

  • AtomicInteger源码分析

    在Java的多线程开发中需要做一些同步的操作。在java concurrent库中提供了一系列支持原子操作的类,在...

网友评论

    本文标题: [Java并发系列] 2.Java中的原子操作类

    本文链接:https://www.haomeiwen.com/subject/mkgpuxtx.html