zoukankan      html  css  js  c++  java
  • Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类

    概要

    AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似。本章以AtomicLongArray对数组类型的原子类进行介绍。内容包括:
    AtomicLongArray介绍和函数列表
    AtomicLongArray源码分析(基于JDK1.7.0_40)
    AtomicLongArray示例

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3514604.html

    AtomicLongArray介绍和函数列表

    在"Java多线程系列--“JUC原子类”02之 AtomicLong原子类"中介绍过,AtomicLong是作用是对长整形进行原子操作。而AtomicLongArray的作用则是对"长整形数组"进行原子操作。

    AtomicLongArray函数列表

    复制代码
    // 创建给定长度的新 AtomicLongArray。
    AtomicLongArray(int length)
    // 创建与给定数组具有相同长度的新 AtomicLongArray,并从给定数组复制其所有元素。
    AtomicLongArray(long[] array)
    
    // 以原子方式将给定值添加到索引 i 的元素。
    long addAndGet(int i, long delta)
    // 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
    boolean compareAndSet(int i, long expect, long update)
    // 以原子方式将索引 i 的元素减1。
    long decrementAndGet(int i)
    // 获取位置 i 的当前值。
    long get(int i)
    // 以原子方式将给定值与索引 i 的元素相加。
    long getAndAdd(int i, long delta)
    // 以原子方式将索引 i 的元素减 1。
    long getAndDecrement(int i)
    // 以原子方式将索引 i 的元素加 1。
    long getAndIncrement(int i)
    // 以原子方式将位置 i 的元素设置为给定值,并返回旧值。
    long getAndSet(int i, long newValue)
    // 以原子方式将索引 i 的元素加1。
    long incrementAndGet(int i)
    // 最终将位置 i 的元素设置为给定值。
    void lazySet(int i, long newValue)
    // 返回该数组的长度。
    int length()
    // 将位置 i 的元素设置为给定值。
    void set(int i, long newValue)
    // 返回数组当前值的字符串表示形式。
    String toString()
    // 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
    boolean    weakCompareAndSet(int i, long expect, long update)
    复制代码

    AtomicLongArray源码分析(基于JDK1.7.0_40)

    AtomicLongArray的完整源码

     View Code

    AtomicLongArray的代码很简单,下面仅以incrementAndGet()为例,对AtomicLong的原理进行说明。
    incrementAndGet()源码如下:

    public final long incrementAndGet(int i) {
        return addAndGet(i, 1);
    }

    说明:incrementAndGet()的作用是以原子方式将long数组的索引 i 的元素加1,并返回加1之后的值。

    addAndGet()源码如下:

    复制代码
    public long addAndGet(int i, long delta) {
        // 检查数组是否越界
        long offset = checkedByteOffset(i);
        while (true) {
            // 获取long型数组的索引 offset 的原始值
            long current = getRaw(offset);
            // 修改long型值
            long next = current + delta;
            // 通过CAS更新long型数组的索引 offset的值。
            if (compareAndSetRaw(offset, current, next))
                return next;
        }
    }
    复制代码

    说明:addAndGet()首先检查数组是否越界。如果没有越界的话,则先获取数组索引i的值;然后通过CAS函数更新i的值。

    getRaw()源码如下:

    private long getRaw(long offset) {
        return unsafe.getLongVolatile(array, offset);
    }

    说明:unsafe是通过Unsafe.getUnsafe()返回的一个Unsafe对象。通过Unsafe的CAS函数对long型数组的元素进行原子操作。如compareAndSetRaw()就是调用Unsafe的CAS函数,它的源码如下:

    private boolean compareAndSetRaw(long offset, long expect, long update) {
        return unsafe.compareAndSwapLong(array, offset, expect, update);
    }

    AtomicLongArray示例

    复制代码
     1 // LongArrayTest.java的源码
     2 import java.util.concurrent.atomic.AtomicLongArray;
     3 
     4 public class LongArrayTest {
     5     
     6     public static void main(String[] args){
     7 
     8         // 新建AtomicLongArray对象
     9         long[] arrLong = new long[] {10, 20, 30, 40, 50};
    10         AtomicLongArray ala = new AtomicLongArray(arrLong);
    11 
    12         ala.set(0, 100);
    13         for (int i=0, len=ala.length(); i<len; i++) 
    14             System.out.printf("get(%d) : %s
    ", i, ala.get(i));
    15 
    16         System.out.printf("%20s : %s
    ", "getAndDecrement(0)", ala.getAndDecrement(0));
    17         System.out.printf("%20s : %s
    ", "decrementAndGet(1)", ala.decrementAndGet(1));
    18         System.out.printf("%20s : %s
    ", "getAndIncrement(2)", ala.getAndIncrement(2));
    19         System.out.printf("%20s : %s
    ", "incrementAndGet(3)", ala.incrementAndGet(3));
    20 
    21         System.out.printf("%20s : %s
    ", "addAndGet(100)", ala.addAndGet(0, 100));
    22         System.out.printf("%20s : %s
    ", "getAndAdd(100)", ala.getAndAdd(1, 100));
    23 
    24         System.out.printf("%20s : %s
    ", "compareAndSet()", ala.compareAndSet(2, 31, 1000));
    25         System.out.printf("%20s : %s
    ", "get(2)", ala.get(2));
    26     }
    27 }
    复制代码

    运行结果

    复制代码
    get(0) : 100
    get(1) : 20
    get(2) : 30
    get(3) : 40
    get(4) : 50
      getAndDecrement(0) : 100
      decrementAndGet(1) : 19
      getAndIncrement(2) : 30
      incrementAndGet(3) : 41
          addAndGet(100) : 199
          getAndAdd(100) : 19
         compareAndSet() : true
                  get(2) : 1000

    转自:http://www.cnblogs.com/skywang12345/p/3514604.html

  • 相关阅读:
    C++编程开发学习的50条建议(转)
    编程思想:我现在是这样编程的(转)
    Linux系统编程@多线程与多进程GDB调试
    字符串分割函数 STRTOK & STRTOK_R (转)
    C语言指针与数组的定义与声明易错分析
    C语言 a和&a的区别
    C语言二重指针与malloc
    【C语言入门】C语言的组成结构(基础完整篇)!
    程序员吐槽女友败家:开酒店必须400元起步,工资却不到自己的一半!
    怎样才能和编程语言对上眼?你需要做些准备以及...
  • 原文地址:https://www.cnblogs.com/duanxz/p/3465014.html
Copyright © 2011-2022 走看看