美文网首页
10.原子变量

10.原子变量

作者: 0x70e8 | 来源:发表于2018-08-08 10:04 被阅读0次

原子变量

原子变量是并发包中的一个并发安全工具,相较于普通变量,它提供了与volatile相同的可见性,相较于volatile变量,它又有对于复合操作的原子性(API中的复合操作)。它是一个实用的并发工具。

原子变量相当于一种泛化的volatile变量,能够支持原子的和有条件的读改写操作。它的原子性不是由锁来提供,而是基于硬件支持的CAS指令。如AtomicInteger表示一个int型值,并提供了set和get方法,这与volatile类型的int变量在读取和写入有着同样的内存语义。

java.util.concurrent包提供了12个原子变量类,分为四类:

  • 标量类
  • 更新器类
  • 数组类
  • 复合变量类

最常用的是标量类:AtomicInteger、AtomicLong、AtomICBool饿啊以及AtomicReference。所有这些类都支持CAS,此外AtomicInteger和AtomicLong还提供算术运算。

原子数组类(只支持Integer、Long和Reference版本)中的元素可以实现原子更新。原子数组类为数据的元素提供了volatile类型的访问语义,这是与普通数组不同的地方。

原子变量类是可变类,没有重写hashCode和equals方法,每个示例都是不同的。与其他可变对象相同,他们也不适合做基于散列的容器中的键值。

看一下AtomicInteger的部分源码,了解一下它的实现原理:


package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;

/**
 * @since 1.5
 * @author Doug Lea
*/
public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    // unsafe类提供了CAS的调用接口,这是原子类的核心基础
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    // 可以发现,内部存储int值的变量是volatile变量,所以说提供了volatile的语义
    private volatile int value;

 
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

 
    public AtomicInteger() {
    }

  
    public final int get() {
        return value;
    }

 
    public final void set(int newValue) {
        value = newValue;
    }

 
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

 // 这是个复合操作,使用的是Unsafe类,底层使用的就是CAS
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

 
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

 
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

 
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

 
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }

 
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

     
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

    
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }
 
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

    
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    
    public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }

    
    public final int getAndAccumulate(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    
    public final int accumulateAndGet(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return next;
    }

   
    public String toString() {
        return Integer.toString(get());
    }

     
    public int intValue() {
        return get();
    }

    
    public long longValue() {
        return (long)get();
    }

     
    public float floatValue() {
        return (float)get();
    }

    
    public double doubleValue() {
        return (double)get();
    }

}

参考资料

[1] Java并发编程实战

相关文章

  • 10.原子变量

    原子变量 原子变量是并发包中的一个并发安全工具,相较于普通变量,它提供了与volatile相同的可见性,相较于vo...

  • 原子变量

    C++11 提供了一个原子类型std::atomic 。使用原子变量就不用锁了,因为本来就是互斥访问. 使用...

  • 分布式事务

    1、线程安全保证线程安全一般分成两种方式:锁和原子变量原子变量:原子变量能够保证原子性的操作,意思是某个任务在执行...

  • Java并发编程之原子变量

    原子变量最主要的一个特点就是所有的操作都是原子的,synchronized关键字也可以做到对变量的原子操作。只是s...

  • Java并发编程之原子变量

    原子变量最主要的一个特点就是所有的操作都是原子的,synchronized关键字也可以做到对变量的原子操作。只是s...

  • 原子类与原子操作 2022-05-05

    go变量原子操作最简单的方式就是给变量配一把锁,然后在操作这个变量的方法中都加锁放锁 如【原子int】:

  • 全面了解 Java 原子变量类

    ? 本文以及示例源码已归档在 javacore 一、原子变量类简介 为何需要原子变量类 保证线程安全是 Java ...

  • 7. Java中的13个原子操作类

    原子操作 一种用法简单、性能高效、线程安全的更新变量的方式,包括原子更新基本类型、原子更新数组、原子更新引用、原子...

  • c++11中的特性

    1、原子类型:atomic<> : 变量执行++操作是一个原子的操作2、条件变量的使用使用对象调用方法的形式...

  • Java并发学习之synchronized(一)

    synchronized 具有原子性,可见性。原子性:由java内存模型来直接保证的原子性变量操作包括read,l...

网友评论

      本文标题:10.原子变量

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