Java concurrency之AtomicLongArray原子类_动力节点Java学院整理
程序员文章站
2023-12-18 21:28:40
atomiclongarray介绍和函数列表
atomiclongarray函数列表
// 创建给定长度的新 atomiclongarray。...
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) : 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
以上所述是小编给大家介绍的java concurrency之atomiclongarray原子类,希望对大家有所帮助
推荐阅读
-
Java concurrency之AtomicLongArray原子类_动力节点Java学院整理
-
Java concurrency之AtomicLong原子类_动力节点Java学院整理
-
Java concurrency线程池之Callable和Future_动力节点Java学院整理
-
Java concurrency之AtomicLongFieldUpdater原子类_动力节点Java学院整理
-
Java concurrency之AtomicReference原子类_动力节点Java学院整理
-
Java8新特性之泛型的目标类型推断_动力节点Java学院整理
-
Java8新特性之StampedLock_动力节点Java学院整理
-
Java concurrency之锁_动力节点Java学院整理
-
Java8新特性之JavaFX 8_动力节点Java学院整理
-
Java8新特性之Base64详解_动力节点Java学院整理