1、原子更新基本类型
AtomicInteger 原子更新整型
主要方法
//返回当前值
public final int get() {
return value;
}
//设置为给定值
public final void set(int newValue) {
value = newValue;
}
//原子设置为给定值并返回旧值。
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
//比较当前值=预期值,则自动将该值设置为给定的更新值
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
//以原子方式将当前值递增1,返回更新前的值
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
//以原子方式将当前值递增1,返回更新后的值
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
//以原子方式将当前值递减1,返回更新前的值
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
//以原子方式将当前值递减1,返回更新后的值
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
//以原子方式将给定值与当前值相加,返回更新前的值
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
//以原子方式将给定值与当前值相加,返回更新后的值
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
示例1 最终结果不一致问题
public static int a = 0;
private static void demo01() {
Thread t1 = new Thread(AtomicDemo::method01, "t1");
Thread t2 = new Thread(AtomicDemo::method01, "t2");
Thread t3 = new Thread(AtomicDemo::method01, "t3");
t1.start();
t2.start();
t3.start();
while (Thread.activeCount() > 1) Thread.yield();
System.out.println(a);
}
private static void method01() {
String thName = Thread.currentThread().getName();
System.err.println("线程:" + thName + " >> " + a);
for (int i = 0; i < 1000; i++) {
a++;
}
System.out.println("线程:" + thName + " >> " + a);
}
多次测试,不能保证结果一致性
可以通过添加 synchronized 关键字同步方法来保证一致性,但synchronized属重量级锁,耗性能。
private synchronized static void method01() {
String thName = Thread.currentThread().getName();
System.err.println("线程:" + thName + " >> " + a);
for (int i = 0; i < 1000; i++) {
a++;
}
System.out.println("线程:" + thName + " >> " + a);
}
示例2 原子操作类AtomicInteger
public static AtomicInteger b = new AtomicInteger();
private static void demo02() {
Thread t1 = new Thread(AtomicDemo::method02, "t1");
Thread t2 = new Thread(AtomicDemo::method02, "t2");
Thread t3 = new Thread(AtomicDemo::method02, "t3");
t1.start();
t2.start();
t3.start();
while (Thread.activeCount() > 1) Thread.yield();
System.out.println(b.get());
}
private static void method02() {
String thName = Thread.currentThread().getName();
System.err.println("线程:" + thName + " >> " + b.get());
for (int i = 0; i < 1000; i++) {
b.incrementAndGet();
}
System.out.println("线程:" + thName + " >> " + b.get());
}
多次测试,能保证结果一致性
AtomicLong:原子更新长整型
AtomicBoolean:原子更新布尔类型
2、原子更新引用类型
AtomicReference:原子更新引用类型
主要方法
//获取当前值
public final V get() {
return value;
}
//设置为给定值
public final void set(V newValue) {
value = newValue;
}
//比较当前值=预期值,则自动将该值设置为给定的更新值。
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
//原子设置为给定值并返回旧值
public final V getAndSet(V newValue) {
return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
}
private static void demo03() {
AtomicReference<String> ars = new AtomicReference<>("字符串");
System.out.println(ars.get());
ars.compareAndSet("预期值", "更新值");
System.out.println(ars.get());
//或者实体类、数组等
//AtomicReference<AtomicDemo> ars2 = new AtomicReference<>(new AtomicDemo());
}
AtomicMarkableReference:原子更新一个对象引用和一个标记位
主要方法
//返回引用的当前值
public V getReference() {
return pair.reference;
}
//返回标记的当前值
public boolean isMarked() {
return pair.mark;
}
//如果当前引用等于预期引用,则原子地将标记的值设置为给定的更新值
public boolean attemptMark(V expectedReference, boolean newMark) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
(newMark == current.mark ||
casPair(current, Pair.of(expectedReference, newMark)));
}
//如果当前引用等于预期引用,且当前标记等于预期标记,则原子地将引用和标记的值都设置为给定的更新值
public boolean compareAndSet(V expectedReference,
V newReference,
boolean expectedMark,
boolean newMark) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedMark == current.mark &&
((newReference == current.reference &&
newMark == current.mark) ||
casPair(current, Pair.of(newReference, newMark)));
}
private static void demo04() {
AtomicMarkableReference<Integer> amsi = new AtomicMarkableReference<>(0, false);
System.out.println("更新前:" + amsi.isMarked());
System.out.println("更新前:" + amsi.getReference());
//未被标记,进行标志
if (!amsi.isMarked() && amsi.attemptMark(0,true)) {
//更新
if (amsi.compareAndSet(0, 1, true, false)) {
System.out.println("更新成功");
} else {
System.out.println("更新失败");
}
}
System.out.println("更新后:" + amsi.isMarked());
System.out.println("更新后:" + amsi.getReference());
}
AtomicStampedReference:原子更新一个对象引用和一个整型
主要方法
//返回引用的当前值
public V getReference() {
return pair.reference;
}
//返回戳记的当前值
public int getStamp() {
return pair.stamp;
}
//如果当前引用等于预期引用,则原子地将戳记的值设置为给定的更新值
public boolean attemptStamp(V expectedReference, int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
(newStamp == current.stamp ||
casPair(current, Pair.of(expectedReference, newStamp)));
}
//如果当前引用等于预期引用,且当前戳记等于预期戳记,则原子地将引用和戳记的值都设置为给定的更新值
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
private static void demo05() {
AtomicStampedReference<String> asrs = new AtomicStampedReference<>("初始值", 1);
System.out.println("更新前:" + asrs.getStamp());
System.out.println("更新前:" + asrs.getReference());
//更新
if (asrs.compareAndSet("预期值=初始值", "更新值", 1, asrs.getStamp() + 1)) {
System.out.println("更新成功");
} else {
System.out.println("更新失败");
}
System.out.println("更新后:" + asrs.getStamp());
System.out.println("更新后:" + asrs.getReference());
}
3、原子更新数组
AtomicIntegerArray:原子更新整型数组里的元素
主要方法
//返回数组的长度
public final int length() {
return array.length;
}
//获取索引位置i处的当前值。
public final int get(int i) {
return getRaw(checkedByteOffset(i));
}
//将索引位置i处的元素设置为给定值。
public final void set(int i, int newValue) {
unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
}
//原子地将索引位置i处的元素设置为给定值,并返回旧值
public final int getAndSet(int i, int newValue) {
return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
}
//比较当前值=预期值,则原子地将索引位置i处的元素设置为给定的更新值。
public final boolean compareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
//索引i处的元素按原子级递增1。返回更新前的值
public final int getAndIncrement(int i) {
return getAndAdd(i, 1);
}
//索引i处的元素按原子级递减1。返回更新前的值
public final int getAndDecrement(int i) {
return getAndAdd(i, -1);
}
//索引i处的元素按原子方式与给定值相加。返回更新前的值
public final int getAndAdd(int i, int delta) {
return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
}
//索引i处的元素按原子级递增1。返回更新后的值
public final int incrementAndGet(int i) {
return getAndAdd(i, 1) + 1;
}
//索引i处的元素按原子级递减1。返回更新后的值
public final int decrementAndGet(int i) {
return getAndAdd(i, -1) - 1;
}
//索引i处的元素按原子方式与给定值相加。返回更新后的值
public final int addAndGet(int i, int delta) {
return getAndAdd(i, delta) + delta;
}
private static void demo06() {
int[] is = {1, 2, 3, 4, 5};
AtomicIntegerArray aia = new AtomicIntegerArray(is);
System.out.println(aia);
System.out.println(aia.getAndAdd(1, 10));
System.out.println(aia);
}
AtomicLongArray:原子更新长整型数组里的元素
AtomicReferenceArray:原子更新引用类型数组里的元素
4、原子更新字段类型
AtomicIntegerFieldUpdater:原子更新整型字段类型
//获取此更新程序管理的给定对象字段中的当前值
public abstract int get(T obj);
//如果当前值==预期值,则自动将此更新程序管理的给定对象的字段设置为给定的更新值
public abstract boolean compareAndSet(T obj, int expect, int update);
//原子地将此更新程序管理的给定对象的字段设置为给定值,并返回旧值
public int getAndSet(T obj, int newValue);
//此更新程序管理的给定对象的字段的当前值以原子方式递增1,并返回旧值
public int getAndIncrement(T obj);
//此更新程序管理的给定对象的字段的当前值以原子方式递减1,并返回旧值
public int getAndDecrement(T obj);
//以原子方式将给定值添加到此更新程序管理的给定对象的字段的当前值,并返回旧值
public int getAndAdd(T obj, int delta)
//此更新程序管理的给定对象的字段的当前值以原子方式递增1,并返回新值
public int incrementAndGet(T obj);
//此更新程序管理的给定对象的字段的当前值以原子方式递减1,并返回新值
public int decrementAndGet(T obj);
//以原子方式将给定值添加到此更新程序管理的给定对象的字段的当前值,并返回新值
public int addAndGet(T obj, int delta)
private static void demo07() {
AtomicDemo demo = new AtomicDemo();
AtomicIntegerFieldUpdater<AtomicDemo> aifu = AtomicIntegerFieldUpdater.newUpdater(AtomicDemo.class, "age");
System.out.println(demo.age);
System.out.println(aifu.get(demo));
System.out.println(aifu.getAndIncrement(demo));
System.out.println(demo.age);
System.out.println(aifu.get(demo));
}