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

网友投稿 228 2023-05-10


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

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 http://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.

*

*

May fail spuriously

* 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

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原子类,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!

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原子类,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java concurrency之AtomicLongFieldUpdater原子类_动力节点Java学院整理
下一篇:详解使用Spring的restTemplete进行Http请求
相关文章

 发表评论

暂时没有评论,来抢沙发吧~