首页 > 开发 > Java > 正文

Java concurrency之AtomicLongArray原子类_动力节点Java学院整理

2024-07-13 10:08:38
字体:
来源:转载
供稿:网友

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

 /*  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */ /*  *  *  *  *  *  * Written by Doug Lea with assistance from members of JCP JSR-  * Expert Group and released to the public domain, as explained at  * http://creativecommons.org/publicdomain/zero/./  */ package java.util.concurrent.atomic; import sun.misc.Unsafe; import java.util.*; /**  * A {@code long} array in which elements may be updated atomically.  * See the {@link java.util.concurrent.atomic} package specification  * for description of the properties of atomic variables.  * @since .  * @author Doug Lea  */ public class AtomicLongArray implements java.io.Serializable {   private static final long serialVersionUID = -2308431214976778248L;   private static final Unsafe unsafe = Unsafe.getUnsafe();   private static final int base = unsafe.arrayBaseOffset(long[].class);   private static final int shift;   private final long[] array;   static {     int scale = unsafe.arrayIndexScale(long[].class);     if ((scale & (scale - )) != )       throw new Error("data type scale not a power of two");     shift = - Integer.numberOfLeadingZeros(scale);   }   private long checkedByteOffset(int i) {     if (i < || i >= array.length)       throw new IndexOutOfBoundsException("index " + i);     return byteOffset(i);   }   private static long byteOffset(int i) {     return ((long) i << shift) + base;   }   /**    * Creates a new AtomicLongArray of the given length, with all    * elements initially zero.    *    * @param length the length of the array    */   public AtomicLongArray(int length) {     array = new long[length];   }   /**    * Creates a new AtomicLongArray with the same length as, and    * all elements copied from, the given array.    *    * @param array the array to copy elements from    * @throws NullPointerException if array is null    */   public AtomicLongArray(long[] array) {     // Visibility guaranteed by final field guarantees     this.array = array.clone();   }   /**    * Returns the length of the array.    *    * @return the length of the array    */   public final int length() {     return array.length;   }   /**   * Gets the current value at position {@code i}.   *   * @param i the index   * @return the current value   */   public final long get(int i) {     return getRaw(checkedByteOffset(i));   }   private long getRaw(long offset) {     return unsafe.getLongVolatile(array, offset);   }   /**   * Sets the element at position {@code i} to the given value.   *   * @param i the index   * @param newValue the new value   */   public final void set(int i, long newValue) {     unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);   }   /**   * Eventually sets the element at position {@code i} to the given value.   *   * @param i the index   * @param newValue the new value   * @since 1.6   */   public final void lazySet(int i, long newValue) {     unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);   }   /**   * Atomically sets the element at position {@code i} to the given value   * and returns the old value.   *   * @param i the index   * @param newValue the new value   * @return the previous value   */   public final long getAndSet(int i, long newValue) {     long offset = checkedByteOffset(i);     while (true) {       long current = getRaw(offset);       if (compareAndSetRaw(offset, current, newValue))         return current;     }   }   /**   * Atomically sets the element at position {@code i} to the given   * updated value if the current value {@code ==} the expected value.   *   * @param i the index   * @param expect the expected value   * @param update the new value   * @return true if successful. False return indicates that   * the actual value was not equal to the expected value.   */   public final boolean compareAndSet(int i, long expect, long update) {     return compareAndSetRaw(checkedByteOffset(i), expect, update);   }   private boolean compareAndSetRaw(long offset, long expect, long update) {     return unsafe.compareAndSwapLong(array, offset, expect, update);   }   /**   * Atomically sets the element at position {@code i} to the given   * updated value if the current value {@code ==} the expected value.   *   * <p>May <a href="package-summary.html#Spurious" rel="external nofollow" >fail spuriously</a>   * and does not provide ordering guarantees, so is only rarely an   * appropriate alternative to {@code compareAndSet}.   *   * @param i the index   * @param expect the expected value   * @param update the new value   * @return true if successful.   */   public final boolean weakCompareAndSet(int i, long expect, long update) {     return compareAndSet(i, expect, update);   }   /**   * Atomically increments by one the element at index {@code i}.   *   * @param i the index   * @return the previous value   */   public final long getAndIncrement(int i) {     return getAndAdd(i, 1);   }   /**   * Atomically decrements by one the element at index {@code i}.   *   * @param i the index   * @return the previous value   */   public final long getAndDecrement(int i) {     return getAndAdd(i, -1);   }   /**   * Atomically adds the given value to the element at index {@code i}.   *   * @param i the index   * @param delta the value to add   * @return the previous value   */   public final long getAndAdd(int i, long delta) {     long offset = checkedByteOffset(i);     while (true) {       long current = getRaw(offset);       if (compareAndSetRaw(offset, current, current + delta))         return current;     }   }   /**   * Atomically increments by one the element at index {@code i}.   *   * @param i the index   * @return the updated value   */   public final long incrementAndGet(int i) {     return addAndGet(i, 1);   }   /**   * Atomically decrements by one the element at index {@code i}.   *   * @param i the index   * @return the updated value   */   public final long decrementAndGet(int i) {     return addAndGet(i, -1);   }   /**   * Atomically adds the given value to the element at index {@code i}.   *   * @param i the index   * @param delta the value to add   * @return the updated value   */   public long addAndGet(int i, long delta) {     long offset = checkedByteOffset(i);     while (true) {       long current = getRaw(offset);       long next = current + delta;       if (compareAndSetRaw(offset, current, next))         return next;     }   }   /**   * Returns the String representation of the current values of array.   * @return the String representation of the current values of array   */   public String toString() {     int iMax = array.length - 1;     if (iMax == -1)       return "[]";     StringBuilder b = new StringBuilder();     b.append('[');     for (int i = 0; ; i++) {       b.append(getRaw(byteOffset(i)));       if (i == iMax)         return b.append(']').toString();       b.append(',').append(' ');     }   } }

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示例

 // LongArrayTest.java的源码 import java.util.concurrent.atomic.AtomicLongArray; public class LongArrayTest {   public static void main(String[] args){     // 新建AtomicLongArray对象     long[] arrLong = new long[] {10, 20, 30, 40, 50};     AtomicLongArray ala = new AtomicLongArray(arrLong);     ala.set(0, 100);     for (int i=0, len=ala.length(); i<len; i++)        System.out.printf("get(%d) : %s/n", i, ala.get(i));     System.out.printf("%20s : %s/n", "getAndDecrement(0)", ala.getAndDecrement(0));     System.out.printf("%20s : %s/n", "decrementAndGet(1)", ala.decrementAndGet(1));     System.out.printf("%20s : %s/n", "getAndIncrement(2)", ala.getAndIncrement(2));     System.out.printf("%20s : %s/n", "incrementAndGet(3)", ala.incrementAndGet(3));     System.out.printf("%20s : %s/n", "addAndGet(100)", ala.addAndGet(0, 100));     System.out.printf("%20s : %s/n", "getAndAdd(100)", ala.getAndAdd(1, 100));     System.out.printf("%20s : %s/n", "compareAndSet()", ala.compareAndSet(2, 31, 1000));     System.out.printf("%20s : %s/n", "get(2)", ala.get(2));   } }

运行结果:

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

以上所述是小编给大家介绍的Java concurrency之AtomicLongArray原子类,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对VeVb武林网网站的支持!


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表