java中Atomic类之AtomicLongArray

来源:互联网 发布:鱼缸水景设计软件 编辑:程序博客网 时间:2024/06/05 19:58

概要

AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似。本章以AtomicLongArray对数组类型的原子类进行介绍.

 

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的完整源码

复制代码
  1 /*  2  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.  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  * 31  * Written by Doug Lea with assistance from members of JCP JSR-166 32  * Expert Group and released to the public domain, as explained at 33  * http://creativecommons.org/publicdomain/zero/1.0/ 34  */ 35  36 package java.util.concurrent.atomic; 37 import sun.misc.Unsafe; 38 import java.util.*; 39  40 /** 41  * A {@code long} array in which elements may be updated atomically. 42  * See the {@link java.util.concurrent.atomic} package specification 43  * for description of the properties of atomic variables. 44  * @since 1.5 45  * @author Doug Lea 46  */ 47 public class AtomicLongArray implements java.io.Serializable { 48     private static final long serialVersionUID = -2308431214976778248L; 49  50     private static final Unsafe unsafe = Unsafe.getUnsafe(); 51     private static final int base = unsafe.arrayBaseOffset(long[].class); 52     private static final int shift; 53     private final long[] array; 54  55     static { 56         int scale = unsafe.arrayIndexScale(long[].class); 57         if ((scale & (scale - 1)) != 0) 58             throw new Error("data type scale not a power of two"); 59         shift = 31 - Integer.numberOfLeadingZeros(scale); 60     } 61  62     private long checkedByteOffset(int i) { 63         if (i < 0 || i >= array.length) 64             throw new IndexOutOfBoundsException("index " + i); 65  66         return byteOffset(i); 67     } 68  69     private static long byteOffset(int i) { 70         return ((long) i << shift) + base; 71     } 72  73     /** 74      * Creates a new AtomicLongArray of the given length, with all 75      * elements initially zero. 76      * 77      * @param length the length of the array 78      */ 79     public AtomicLongArray(int length) { 80         array = new long[length]; 81     } 82  83     /** 84      * Creates a new AtomicLongArray with the same length as, and 85      * all elements copied from, the given array. 86      * 87      * @param array the array to copy elements from 88      * @throws NullPointerException if array is null 89      */ 90     public AtomicLongArray(long[] array) { 91         // Visibility guaranteed by final field guarantees 92         this.array = array.clone(); 93     } 94  95     /** 96      * Returns the length of the array. 97      * 98      * @return the length of the array 99      */100     public final int length() {101         return array.length;102     }103 104     /**105      * Gets the current value at position {@code i}.106      *107      * @param i the index108      * @return the current value109      */110     public final long get(int i) {111         return getRaw(checkedByteOffset(i));112     }113 114     private long getRaw(long offset) {115         return unsafe.getLongVolatile(array, offset);116     }117 118     /**119      * Sets the element at position {@code i} to the given value.120      *121      * @param i the index122      * @param newValue the new value123      */124     public final void set(int i, long newValue) {125         unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);126     }127 128     /**129      * Eventually sets the element at position {@code i} to the given value.130      *131      * @param i the index132      * @param newValue the new value133      * @since 1.6134      */135     public final void lazySet(int i, long newValue) {136         unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);137     }138 139 140     /**141      * Atomically sets the element at position {@code i} to the given value142      * and returns the old value.143      *144      * @param i the index145      * @param newValue the new value146      * @return the previous value147      */148     public final long getAndSet(int i, long newValue) {149         long offset = checkedByteOffset(i);150         while (true) {151             long current = getRaw(offset);152             if (compareAndSetRaw(offset, current, newValue))153                 return current;154         }155     }156 157     /**158      * Atomically sets the element at position {@code i} to the given159      * updated value if the current value {@code ==} the expected value.160      *161      * @param i the index162      * @param expect the expected value163      * @param update the new value164      * @return true if successful. False return indicates that165      * the actual value was not equal to the expected value.166      */167     public final boolean compareAndSet(int i, long expect, long update) {168         return compareAndSetRaw(checkedByteOffset(i), expect, update);169     }170 171     private boolean compareAndSetRaw(long offset, long expect, long update) {172         return unsafe.compareAndSwapLong(array, offset, expect, update);173     }174 175     /**176      * Atomically sets the element at position {@code i} to the given177      * updated value if the current value {@code ==} the expected value.178      *179      * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>180      * and does not provide ordering guarantees, so is only rarely an181      * appropriate alternative to {@code compareAndSet}.182      *183      * @param i the index184      * @param expect the expected value185      * @param update the new value186      * @return true if successful.187      */188     public final boolean weakCompareAndSet(int i, long expect, long update) {189         return compareAndSet(i, expect, update);190     }191 192     /**193      * Atomically increments by one the element at index {@code i}.194      *195      * @param i the index196      * @return the previous value197      */198     public final long getAndIncrement(int i) {199         return getAndAdd(i, 1);200     }201 202     /**203      * Atomically decrements by one the element at index {@code i}.204      *205      * @param i the index206      * @return the previous value207      */208     public final long getAndDecrement(int i) {209         return getAndAdd(i, -1);210     }211 212     /**213      * Atomically adds the given value to the element at index {@code i}.214      *215      * @param i the index216      * @param delta the value to add217      * @return the previous value218      */219     public final long getAndAdd(int i, long delta) {220         long offset = checkedByteOffset(i);221         while (true) {222             long current = getRaw(offset);223             if (compareAndSetRaw(offset, current, current + delta))224                 return current;225         }226     }227 228     /**229      * Atomically increments by one the element at index {@code i}.230      *231      * @param i the index232      * @return the updated value233      */234     public final long incrementAndGet(int i) {235         return addAndGet(i, 1);236     }237 238     /**239      * Atomically decrements by one the element at index {@code i}.240      *241      * @param i the index242      * @return the updated value243      */244     public final long decrementAndGet(int i) {245         return addAndGet(i, -1);246     }247 248     /**249      * Atomically adds the given value to the element at index {@code i}.250      *251      * @param i the index252      * @param delta the value to add253      * @return the updated value254      */255     public long addAndGet(int i, long delta) {256         long offset = checkedByteOffset(i);257         while (true) {258             long current = getRaw(offset);259             long next = current + delta;260             if (compareAndSetRaw(offset, current, next))261                 return next;262         }263     }264 265     /**266      * Returns the String representation of the current values of array.267      * @return the String representation of the current values of array268      */269     public String toString() {270         int iMax = array.length - 1;271         if (iMax == -1)272             return "[]";273 274         StringBuilder b = new StringBuilder();275         b.append('[');276         for (int i = 0; ; i++) {277             b.append(getRaw(byteOffset(i)));278             if (i == iMax)279                 return b.append(']').toString();280             b.append(',').append(' ');281         }282     }283 284 }
复制代码

 

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\n", i, ala.get(i));15 16         System.out.printf("%20s : %s\n", "getAndDecrement(0)", ala.getAndDecrement(0));17         System.out.printf("%20s : %s\n", "decrementAndGet(1)", ala.decrementAndGet(1));18         System.out.printf("%20s : %s\n", "getAndIncrement(2)", ala.getAndIncrement(2));19         System.out.printf("%20s : %s\n", "incrementAndGet(3)", ala.incrementAndGet(3));20 21         System.out.printf("%20s : %s\n", "addAndGet(100)", ala.addAndGet(0, 100));22         System.out.printf("%20s : %s\n", "getAndAdd(100)", ala.getAndAdd(1, 100));23 24         System.out.printf("%20s : %s\n", "compareAndSet()", ala.compareAndSet(2, 31, 1000));25         System.out.printf("%20s : %s\n", "get(2)", ala.get(2));26     }27 }
复制代码

运行结果

复制代码
get(0) : 100get(1) : 20get(2) : 30get(3) : 40get(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
复制代码
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米手机太卡了怎么办 红米手机太卡怎么办? 红米3老是死机怎么办 红米3s经常死机怎么办 红米4a进水了怎么办 魅族耳机声音小怎么办 魅蓝note6声音小怎么办 魅蓝3s锁定怎么办 红米1密码忘了怎么办 小米手环升级失败怎么办 红米4忘记密码怎么办 红米1代忘记密码怎么办 红米3s忘记密码怎么办 小米3卡槽卡住了怎么办 红米4手机信号不好怎么办 红米note3信号差怎么办 红米note3没信号怎么办 红米3运行慢怎么办 红米手机运行慢怎么办 红米手机忘记解锁图案怎么办 小米手机解锁图案忘了怎么办 红米2内屏坏了怎么办 红米密码忘记了怎么办 红米pro玩王者卡怎么办 红米note4不支持计步怎么办 红米pro玩游戏卡怎么办 红米手机费电快怎么办 荣耀5c忘记密码怎么办 小米之家不退货怎么办 手机号绑定过多小米账户怎么办 耐克黑色鞋褪色怎么办 买广汽传祺7s新车有问题怎么办 华为荣耀10边框掉色了怎么办 网购商家打来无货怎么办 客户拍了不发货怎么办 天猫商家欺骗买家怎么办 阿里买家投诉我发空包怎么办 苹果6s电池坏了怎么办 hm买的单鞋脏了怎么办 微店违规屏蔽搜索怎么办 ios微信支付失效怎么办