目录
一、简介
二、分类
2.1 基本类型原子类
2.1.1 AtomicInteger和AtomicLong介绍
2.1.1.1 AtomicInteger常用的API源码和注释
2.1.1.2 AtomicInteger常用API使用案例
2.1.2 AtomicBoolean介绍
2.1.2.1 AtomicBoolean常用API源码和注释
2.1.2.2 AtomicBoolean常用API使用案例
2.2 数组类型
2.2.1 AtomicIntegerArray和AtomicLongArray介绍
2.2.1.1 AtomicIntegerArray常用的API源码和注释
2.2.1.2 AtomicIntegerArray常用API使用案例
2.2.2 AtomicReferenceArray介绍
2.2.2.1 AtomicReferenceArray常用API源码和注释
2.2.2.2 AtomicReferenceArray常用API使用案例
2.3 引用类型
2.3.1 AtomicReference介绍
2.3.2.1 AtomicReference常用API源码和注释
2.3.3.1 AtomicReference常用API使用案例
2.3.2 AtomicMarkableReference和AtomicStampedReference介绍
2.3.2.1 AtomicMarkableReference常用API源码和注释
2.3.2.2 AtomicMarkableReference常用API使用案例
2.4 对象属性修改类型
2.4.1 对象属性修改原理
2.4.2 AtomicIntegerFieldUpdater和AtomicLongFieldUpdater介绍
2.4.4.1 AtomicIntegerFieldUpdater常用API源码和注释
2.4.4.2 AtomicIntegerFieldUpdater常用API使用案例
2.4.3 AtomicReferenceFieldUpdater介绍
2.4.3.1 AtomicReferenceFieldUpdater常用API源码和注释
2.4.3.2 AtomicReferenceFieldUpdater常用API使用案例
一、简介
原子类是指具有原子特征的类,这个特征最大的特点就是“不可中断的一个或者一系列操作”,要么全部成功,要么全部失败。
java的迸发包java.util.concurrent.atomic下面提供了非常丰富的原子类
二、分类
按照操作数据类型分类可以分为四大类,分别是
- 基本类型
- 数组类型
- 引用类型
- 对象属性修改类型
2.1 基本类型原子类
- AtomicInteger整形原子类
- AtomicBoolean:布尔型原子类
- AtomicLong:长整型原子类
下面的介绍以JDK11为案例进行介绍
2.1.1 AtomicInteger和AtomicLong介绍
- AtomicInteger整形原子类
AtomicInteger主要用于以原子方式更新Integer数据类型,并且它提供了丰富的API用于一系列的计算
- AtomicLong长整形原子类
AtomicLong作用其实和AtomicInteger是一样的,最大的区别就是作用的数据类型不一致。它的常用API其实是和AtomicInteger相似的,不同的是操作的数据结构不一样,一个长整型原子类,一个是整型原子类。
因为AtomicLong和AtomicInteger最大的区别就是数据类型不一致,所以常用APIAtomicLong这里不进行记录。
2.1.1.1 AtomicInteger常用的API源码和注释
/**
* 获取到当前值
*/
public final int get() {
return value;
}
/**
* 设定一个值
*/
public final void set(int newValue) {
value = newValue;
}
/**
* 最终设定为给定值,但允许之后的其他内存操作重新排序
* 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
*/
public final void lazySet(int newValue) {
U.putIntRelease(this, VALUE, newValue);
}
/**
* 如果当前值等于预期值,则以原子方式将该值设置为给定的更新值,
* 如果更新成功,则返回true,否则返 false
*/
public final boolean compareAndSet(int expectedValue, int newValue) {
return U.compareAndSetInt(this, VALUE, expectedValue, newValue);
}
/**
* 以原子的方式设置为给定值,并返回旧值
*/
public final int getAndSet(int newValue) {
return U.getAndSetInt(this, VALUE, newValue);
}
/**
* 以原子方式将当前值加1,并返回旧值,相当于i++
*/
public final int getAndIncrement() {
return U.getAndAddInt(this, VALUE, 1);
}
/**
* 以原子方式将当前值减1,并返回旧值,相当于i--
*/
public final int getAndDecrement() {
return U.getAndAddInt(this, VALUE, -1);
}
/**
* 以原子方式将给定值加到当前值,并返回旧值
*/
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
/**
* 以原子的方式将当前值加1,并返回新值,相当于++i
*/
public final int incrementAndGet() {
return U.getAndAddInt(this, VALUE, 1) + 1;
}
/**
* 以原子方式将当前值减1,并返回新值,相当于--i
*/
public final int decrementAndGet() {
return U.getAndAddInt(this, VALUE, -1) - 1;
}
/**
* 以原子方式将给定值加到当前值,并返回新值
*/
public final int addAndGet(int delta) {
return U.getAndAddInt(this, VALUE, delta) + delta;
}
/**
* 使用给定的函数,以原子的方式更新当前值,并返回更新后的值,该函数接受一个当前值
* 并计算一个新的值
*/
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev = get(), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext)
next = updateFunction.applyAsInt(prev);
if (weakCompareAndSetVolatile(prev, next))
return next;
haveNext = (prev == (prev = get()));
}
}
/**
* 使用给定函数,以原子方式更新当前值,并返回旧值,该函数接受当前值并计算一个新的值
*/
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev = get(), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext)
next = updateFunction.applyAsInt(prev);
if (weakCompareAndSetVolatile(prev, next))
return prev;
haveNext = (prev == (prev = get()));
}
}
/**
* 使用给定的函数和值以原子方式更新当前值,并返回一个新的值。
*/
public final int getAndAccumulate(int x,
IntBinaryOperator accumulatorFunction) {
int prev = get(), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext)
next = accumulatorFunction.applyAsInt(prev, x);
if (weakCompareAndSetVolatile(prev, next))
return prev;
haveNext = (prev == (prev = get()));
}
}
2.1.1.2 AtomicInteger常用API使用案例
ThreadPolUtils工具类:线程池工具类_java线程池工具类-CSDN博客
public static void main(String[] args) {
AtomicInteger integer = new AtomicInteger();
integer.set(1); // 设置值
System.out.println(integer.get()); //输出值
System.out.println("--------------------------------------------------");
// ThreadPoolUtils.execute(() -> {
// for (int i = 0; i < 100; i++) {
// if (i % 10 == 0) {
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// System.out.println(integer.get());
// }
// });
// ThreadPoolUtils.execute(() -> {
// try {
// Thread.sleep(1000);
// System.out.println("-----这个时候对integer进行了变更-----");
// integer.lazySet(222); //如果是set方法,那么还有可能出现获取到1的情况
// for (int i = 0; i < 10; i++) {
// System.out.println(integer.get());
// }
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// });
System.out.println("--------------------------------------------------");
// 预计的值并不是 2 所以不会进行更新
boolean a = integer.compareAndSet(2, 10); //输出 false 1
System.out.println(a + " " + integer.get());
// 预计的值为1 这个时候会进行更新
boolean b = integer.compareAndSet(1, 10); //输出 true 10
System.out.println(b + " " + integer.get());
System.out.println("---------------------------------------------------");
int c = integer.getAndSet(20); //返回旧值,将值变更为当前值
System.out.println("返回旧值:" + c + " integer值变更为:" + integer.get()); //输出返回旧值:10 integer值变更为:20
System.out.println("---------------------------------------------------");
integer.set(0);
int aa = integer.getAndIncrement();
System.out.println("integer++:" + aa); //输出0
integer.set(0);
int bb = integer.incrementAndGet();
System.out.println("++integer:" + bb); // 输出1
System.out.println("---------------------------------------------------");
integer.set(1);
int cc = integer.getAndDecrement();
System.out.println("integer--:" + cc); //输出1
integer.set(1);
int dd = integer.decrementAndGet();
System.out.println("--integer:" + dd); //输出0
System.out.println("---------------------------------------------------");
integer.set(0);
int ee = integer.getAndAdd(10);
System.out.println("getAndAdd返回旧值:" + ee); //输出0
integer.set(0);
int gg = integer.addAndGet(10);
System.out.println("addAndGet返回新值:" + gg);// 输出10
System.out.println("--------------------------------------------------");
integer.set(0);
int ab = integer.updateAndGet(i -> i + 10);
System.out.println("updateAndGet返回更新好的值:" + ab);//输出10
integer.set(0);
int ac = integer.getAndUpdate(i -> i + 10);
System.out.println("getAndUpdate返回旧值:" + ac + " 实际计算好的值:" + integer.get());//输出 0 10
System.out.println("--------------------------------------------------");
integer.set(2);
integer.getAndAccumulate(100, (x, y) -> x * y);
System.out.println("getAndAccumulate返回新的值:"+integer.get()); //输出200
}
2.1.2 AtomicBoolean介绍
- AtomicBoolean:布尔型原子类
AtomicBoolean主要用于以原子方式更新Boolean数据类型
2.1.2.1 AtomicBoolean常用API源码和注释
/**
* 期望值与当前值一致的时候,执行变更操作,如果变更成功,则返回true,否则返回false
*/
public final boolean compareAndSet(boolean expectedValue, boolean newValue) {
return VALUE.compareAndSet(this,
(expectedValue ? 1 : 0),
(newValue ? 1 : 0));
}
/**
* 获取到当前值
*/
public final boolean get() {
return value != 0;
}
/**
* 设置一个最新的值,该值的更新对其他线程立即可见
*/
public final void set(boolean newValue) {
value = newValue ? 1 : 0;
}
/**
* 最终设定为给定值
* 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
*/
public final void lazySet(boolean newValue) {
VALUE.setRelease(this, (newValue ? 1 : 0));
}
/**
* 设置一个新值,返回一个旧值
*/
public final boolean getAndSet(boolean newValue) {
return (int)VALUE.getAndSet(this, (newValue ? 1 : 0)) != 0;
}
2.1.2.2 AtomicBoolean常用API使用案例
public static void main(String[] args) {
AtomicBoolean atomicBoolean = new AtomicBoolean();
atomicBoolean.set(true);
System.out.println(atomicBoolean.get());
boolean flag = atomicBoolean.compareAndSet(true,false);
System.out.println("flag:"+flag+" atomicBoolean:"+atomicBoolean.get()); // 变更成功,返回ture,预计值相等,atomicBoolean返回false,设置成功
atomicBoolean.set(true);
boolean flag2 = atomicBoolean.getAndSet(false);
System.out.println("getAndSet设定一个新的值,返回的是旧的值"+flag2);//返回true
}
2.2 数组类型
- AtomicIntegerArray:整形数组原子类
- AtomicLongArray:长整型数组原子类
- AtomicReferenceArray:引用类型数组原子类
2.2.1 AtomicIntegerArray和AtomicLongArray介绍
- AtomicIntegerArray:整形数组原子类
AtomicIntegerArray整型数据原子类,主要是原子的方式去操作整型数组,丰富的API还提供了一系列的计算方式
- AtomicLongArray:长整型数组原子类
AtomicLongArray长整型数组原子类,它和AtomicIntegerArray最大的区别是操作的数据结构数组不一致,AtomicLongArray主要是针对长整型数组
由于AtomicLongArray常用API其实和AtomicIntegerArray极其相似,最大的区别就是数据类型不一致,所以这里就不再对其进行记录,这里不对AtomicLongArray常用API进行记录,如果有问题可以参考AtomicIntegerArray常用API。
2.2.1.1 AtomicIntegerArray常用的API源码和注释
/**
* 获取数组元素值,i是元素的下标
*/
public final int get(int i) {
return (int)AA.getVolatile(array, i);
}
/**
* 设置数组元素值,i是下标,newValue是对应的值
*/
public final void set(int i, int newValue) {
AA.setVolatile(array, i, newValue);
}
/**
* 以原子方式,对下标为i的数组值加delta,并返回一个新值
*/
public final int addAndGet(int i, int delta) {
return (int)AA.getAndAdd(array, i, delta) + delta;
}
/**
* 以原子方式,对下标为i的数组值加delta,并返回一个旧值
*/
public final int getAndAdd(int i, int delta) {
return (int)AA.getAndAdd(array, i, delta);
}
/**
* 以原子的方式给下标i数组赋值,并返回旧值
*/
public final int getAndSet(int i, int newValue) {
return (int)AA.getAndSet(array, i, newValue);
}
/**
* 给数组下标为i的值加1,并返回旧值,相当于数组下标i的值进行a++操作
*/
public final int getAndIncrement(int i) {
return (int)AA.getAndAdd(array, i, 1);
}
/**
* 给数组下标为i的值减1,并返回旧值,相当于数组下标i的值进行a--操作
*/
public final int getAndDecrement(int i) {
return (int)AA.getAndAdd(array, i, -1);
}
/**
* 给数组下标为i的值加1,并返回新值,相当于数组下标i的值进行++a操作
*/
public final int incrementAndGet(int i) {
return (int)AA.getAndAdd(array, i, 1) + 1;
}
/**
* 给数组下标为i的值减1,并返回新值,相当于数组下标i的值进行--a操作
*/
public final int decrementAndGet(int i) {
return (int)AA.getAndAdd(array, i, -1) - 1;
}
/**
*数组下标i的值与期望值一致的时候,就对其值进行更新,更新成功返回true,否则返回false
*/
public final boolean compareAndSet(int i, int expectedValue, int newValue) {
return AA.compareAndSet(array, i, expectedValue, newValue);
}
/**
* 使用给定函数,以原子方式给数组下标i更新当前值,并返回旧值,该函数接受当前值并计算一个新的值
*/
public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
int prev = get(i), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext)
next = updateFunction.applyAsInt(prev);
if (weakCompareAndSetVolatile(i, prev, next))
return prev;
haveNext = (prev == (prev = get(i)));
}
}
/**
* 使用给定的函数和值以原子方式更新数组下标i的值,并返回一个新的值。
*/
public final int getAndAccumulate(int i, int x,
IntBinaryOperator accumulatorFunction) {
int prev = get(i), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext)
next = accumulatorFunction.applyAsInt(prev, x);
if (weakCompareAndSetVolatile(i, prev, next))
return prev;
haveNext = (prev == (prev = get(i)));
}
}
2.2.1.2 AtomicIntegerArray常用API使用案例
public static void main(String[] args) {
// int[] a = new int[12];
// AtomicIntegerArray array = new AtomicIntegerArray(a);
//两种创建数组的方式都是一样的
AtomicIntegerArray array = new AtomicIntegerArray(12);
array.set(1, 10); //给下标1赋值为10
System.out.println(array.get(0) + " " + array.get(1));// 输出0 10
int a = array.addAndGet(1, 10);// 下标1的值+10
System.out.println("addAndGet返回新值:" + a);// 输出20
int b = array.getAndAdd(1, 10);
;// 下标1的值+10
System.out.println("getAndadd返回旧值:" + b);// 输出20
int c = array.getAndSet(0, 10); //给下标0赋值为10
System.out.println("返回旧值:" + c); // 输出 0
System.out.println("--------------------------------------------------------");
array.set(0, 10); //给下标0赋值为10
int d = array.getAndIncrement(0);
System.out.println("下标0的值++:" + d); //输出10
System.out.println("--------------------------------------------------------");
array.set(0, 10); //给下标0赋值为10
int e = array.incrementAndGet(0);
System.out.println("++下标0的值:" + e); //输出11
System.out.println("--------------------------------------------------------");
array.set(0, 10); //给下标0赋值为10
int f = array.getAndDecrement(0);
System.out.println("下标0的值--:" + f); //输出10
System.out.println("--------------------------------------------------------");
array.set(0, 10); //给下标0赋值为10
int g = array.decrementAndGet(0);
System.out.println("--下标0的值:" + g); //输出9
System.out.println("--------------------------------------------------------");
array.set(0, 10); //给下标0赋值为10
int h = array.getAndUpdate(0, x -> x + 10);
System.out.println("返回旧值:" + h + " 新值:" + array.get(0)); // 输出10 20
System.out.println("--------------------------------------------------------");
array.set(0, 10); //给下标0赋值为10
array.getAndAccumulate(0, 100, (x, y) -> x * y);
System.out.println("返回新值:"+array.get(0)); //输出1000
}
2.2.2 AtomicReferenceArray介绍
AtomicLongArray引用数组原子类,它主要针对的是引用类型的操作。
2.2.2.1 AtomicReferenceArray常用API源码和注释
/**
* 获取数组元素值,i是元素的下标
*/
public final E get(int i) {
return (E)AA.getVolatile(array, i);
}
/**
* 设置数组元素值,i是下标,newValue是对应的值
*/
public final void set(int i, E newValue) {
AA.setVolatile(array, i, newValue);
}
/**
* 将位置i处的元素原子设置为给定值,并返回旧值
*/
public final E getAndSet(int i, E newValue) {
return (E)AA.getAndSet(array, i, newValue);
}
/**
* 数组下标i的值与期望值一致的时候,就对其值进行更新,更新成功返回true,否则返回false
*/
public final boolean compareAndSet(int i, E expectedValue, E newValue) {
return AA.compareAndSet(array, i, expectedValue, newValue);
}
/**
* 使用给定函数,以原子方式给数组下标i更新当前值,并返回旧值,该函数接受当前值并计算一个新的值
*/
public final E getAndUpdate(int i, UnaryOperator<E> updateFunction) {
E prev = get(i), next = null;
for (boolean haveNext = false;;) {
if (!haveNext)
next = updateFunction.apply(prev);
if (weakCompareAndSetVolatile(i, prev, next))
return prev;
haveNext = (prev == (prev = get(i)));
}
}
/**
* 使用给定的函数和值以原子方式更新数组下标i的值,并返回一个新的值。
*/
public final E updateAndGet(int i, UnaryOperator<E> updateFunction) {
E prev = get(i), next = null;
for (boolean haveNext = false;;) {
if (!haveNext)
next = updateFunction.apply(prev);
if (weakCompareAndSetVolatile(i, prev, next))
return next;
haveNext = (prev == (prev = get(i)));
}
}
2.2.2.2 AtomicReferenceArray常用API使用案例
public static void main(String[] args) {
User[] users = new User[2];
AtomicReferenceArray array = new AtomicReferenceArray(users);
User user = new User();
user.setAge(10);
user.setName("小明");
array.set(1,user);
System.out.println(array.get(1).toString());
User user1 = (User) array.getAndSet(0,user); //返回旧值,给下标0赋值新值
System.out.println("user1返回旧值:"+user1+" 新值:"+array.get(0)); //旧值输出为null 新值输出user对象值
System.out.println("---------------------------------------------------------------");
User user2 = new User();
user2.setAge(20);
user2.setName("小明");
boolean flag = array.compareAndSet(0,user,user2);//如果当前值与期望值一致,返回true,并更新对应下标值
System.out.println("flag:"+flag+" 新值:"+array.get(0) );//当前值与期望值一致,返回true,并且更新下标为0的数据
System.out.println("---------------------------------------------------------------");
User user3 = (User) array.getAndUpdate(0,x-> {
User user4 = new User();
user4.setName("小明");
user4.setAge(30);
return user4;
});
System.out.println("返回的旧值:"+user3+" 新值:"+array.get(0)); //旧值user3的age为20 新值age为30
System.out.println("---------------------------------------------------------------");
User user5 = (User) array.updateAndGet(0,x-> {
User user4 = new User();
user4.setName("小明");
user4.setAge(40);
return user4;
});
System.out.println("返回的新值:"+user5); //旧值user5的age为40
}
}
class User{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
2.3 引用类型
- AtomicReference:引用类型原子类
- AtomicMarkableReference:原子更新带有标记的引用类型,通过boolean类型判判断数据是否更改过
- AtomicStampedReference:原子更新带有版本号的引用类型。
2.3.1 AtomicReference介绍
- AtomicReference:引用类型原子类
AtomicReference引用类型原子类,主要是对引用类型进行原子性的操作
2.3.2.1 AtomicReference常用API源码和注释
/**
* 获取对象值值
*/
public final V get() {
return value;
}
/**
* 设置对象值
*/
public final void set(V newValue) {
value = newValue;
}
/**
* 设置新的引用对象值,并返回旧值
*/
public final V getAndSet(V newValue) {
return (V)VALUE.getAndSet(this, newValue);
}
/**
* 如果引用的对象跟期望值一致,那么就对其进行更新,并返回ture,否则返回false
*/
public final boolean compareAndSet(V expectedValue, V newValue) {
return VALUE.compareAndSet(this, expectedValue, newValue);
}
/**
* 给定一个函数,以原子的方式更新当前引用对象值,并返回旧值
*/
public final V getAndUpdate(UnaryOperator<V> updateFunction) {
V prev = get(), next = null;
for (boolean haveNext = false;;) {
if (!haveNext)
next = updateFunction.apply(prev);
if (weakCompareAndSetVolatile(prev, next))
return prev;
haveNext = (prev == (prev = get()));
}
}
/**
* 给定一个函数,以原子的方式更新当前引用对象值,并返回新值
*/
public final V updateAndGet(UnaryOperator<V> updateFunction) {
V prev = get(), next = null;
for (boolean haveNext = false;;) {
if (!haveNext)
next = updateFunction.apply(prev);
if (weakCompareAndSetVolatile(prev, next))
return next;
haveNext = (prev == (prev = get()));
}
}
2.3.3.1 AtomicReference常用API使用案例
public class Test {
public static void main(String[] args) {
User user = new User();
user.setName("java");
user.setAge(19);
AtomicReference reference = new AtomicReference();
reference.set(user);
System.out.println("获取引用对象值" + reference.get().toString()); //输出 获取引用对象值User{name='java', age=19}
System.out.println("--------------------------------------------");
User user1 = new User();
user1.setName("中国");
user1.setAge(5000);
User user2 = (User) reference.getAndSet(user1);
System.out.println("返回旧值:" + user2.toString() + " 获取新值:" + reference.get().toString()); // 输出 返回旧值:User{name='java', age=19} 获取新值:User{name='中国', age=5000}
System.out.println("--------------------------------------------");
boolean flag = reference.compareAndSet(user1, user);//预计值一致,返回true,并更新
System.out.println("预计值一致:" + flag + " 更新以后的值:" + reference.get().toString());
System.out.println("--------------------------------------------"); // 输出 预计值一致:true 更新以后的值:User{name='java', age=19}
User user3 = (User) reference.getAndUpdate(x -> {
User user4 = new User();
user4.setAge(200);
user4.setName("美国");
return user4;
});
System.out.println("返回旧值:"+user3.toString()+" 新值:"+reference.get().toString()); //输出 返回旧值:User{name='java', age=19} 新值:User{name='美国', age=200}
System.out.println("--------------------------------------------");
User user5 = (User) reference.updateAndGet(x -> {
User user6 = new User();
user6.setAge(500);
user6.setName("英国");
return user6;
});
System.out.println("返回新值:"+user5.toString()+" 更新的值:"+reference.get().toString());// 输出返回新值:User{name='英国', age=500} 更新的值:User{name='英国', age=500}
}
}
class User {
private String name;
private Integer age;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2.3.2 AtomicMarkableReference和AtomicStampedReference介绍
- AtomicMarkableReference:原子更新带有标记的引用类型
AtomicMarkableReference它也是主要对引用类型进行原子性的操作,但它是带有原子更新标记的引用类型,因为他有一个boolean标记,我们可以通过它来判断这个引用类型是否已经更改过
- AtomicStampedReference:原子更新带有版本号的引用类型
AtomicStampedReference原子更新带有版本号的引用类型。它和AtomicMarkableReference两者都为了解决ABA的问题。最大的区别在AtomicMarkableReference使用整数来判断数据是否已经更改过了,并且会记录更改过几次。AtomicMarkableReference是通过boolean类型进行判断,数据是否已经更改过了。
由于AtomicStampedReference常用的API和AtomicMarkableReference比较相似,不同的是标记类型不一样,所以这里就不再进行记录,如果有问题,可以参考AtomicMarkableReference的API使用方式i
2.3.2.1 AtomicMarkableReference常用API源码和注释
/**
* 构造函数
*/
public AtomicMarkableReference(V initialRef, boolean initialMark) {
pair = Pair.of(initialRef, initialMark);
}
/**
* 以原子方式获取当前引用值
*/
public V getReference() {
return pair.reference;
}
/**
* 以原子的方式获取当前标记值
*/
public boolean isMarked() {
return pair.mark;
}
/**
* 以原子方式获取当前引用值和标记值
*/
public V get(boolean[] markHolder) {
Pair<V> pair = this.pair;
markHolder[0] = pair.mark;
return pair.reference;
}
/**
* 以原子方式同时更新引用值和标记值,当期望引用值不等于当前引用值时,操作失败,返回false
* 当期望标记值不等于当前标记值时,操作失败,返回false,当新的引用值和标记值同时相等,不更新,直
* 接返回ture,当新的引用值和标记值不同时等于当前值,同时设置新的引用值和标记值,返回true
*/
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)));
}
/**
* 以原子方式,设置当前引用值为新值
*/
public void set(V newReference, boolean newMark) {
Pair<V> current = pair;
if (newReference != current.reference || newMark != current.mark)
this.pair = Pair.of(newReference, newMark);
}
/**
* 如果引用值保持不变,以原子的方式将标记值设置为新的值,当期望值与引用值不相同的时候,返回false
* 当操作值与期望值相同的时候,返回true
*/
public boolean attemptMark(V expectedReference, boolean newMark) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
(newMark == current.mark ||
casPair(current, Pair.of(expectedReference, newMark)));
}
2.3.2.2 AtomicMarkableReference常用API使用案例
public class Test {
public static void main(String[] args) {
User user = new User();
user.setName("java");
user.setAge(19);
AtomicMarkableReference reference = new AtomicMarkableReference(user, true);
System.out.println("获取当前引用值:" + reference.getReference().toString());// 输出 获取当前引用值:User{name='java', age=19}
System.out.println("获取到当前标记:" + reference.isMarked());// 输出获取到当前标记:true
System.out.println("--------------------------------------------------------------------");
User user1 = new User();
user1.setName("中国");
user1.setAge(5000);
reference.set(user1, false); //以原子方式设置新值
boolean[] flag = {false};
System.out.println("以原子方式获取当前引用标记值" + reference.get(flag)); // 输出以原子方式获取当前引用标记值User{name='中国', age=5000}
System.out.println("--------------------------------------------------------------------");
User user2 = new User();
user2.setName("美国");
user2.setAge(200);
// 如果期望值于当前引用值一致,那么就会修改预计值,并且修改标记
// 这里期望值是user,跟我们上面设置的值是一致,所以会修改,
// 因为上面的标记是false,跟我们预计的标记也是一致,所以会修改(标记值和预计值一致,返回true)
System.out.println("当前标记:"+reference.isMarked());
boolean flag2 = reference.compareAndSet(user1, user2, false, true);
System.out.println("是否修改:" + flag2 + " 当前值:" + reference.get(flag)); //输出 是否修改:true 当前值:User{name='美国', age=200}
System.out.println("--------------------------------------------------------------------");
//引用值保持不变,变更标记
System.out.println("当前标记:"+reference.isMarked()); //true
boolean flag3 = reference.attemptMark(user2 ,false);
System.out.println(flag3+" 变更以后得标记:"+reference.isMarked());//变更成功 输出 true 变更以后得标记:false
}
}
class User {
private String name;
private Integer age;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2.4 对象属性修改类型
- AtomicIntegerFieldUpdater:原子更新整形字段的更新器
- AtomicLongFieldUpdater:原子更新长整形字段的更新器
- AtomicReferenceFieldUpdater:原子更新引用类型的字段
2.4.1 对象属性修改原理
他们通过基于反射的API实现细粒度的并发控制,主要的作用是用来更新对象的volatile字段。
2.4.2 AtomicIntegerFieldUpdater和AtomicLongFieldUpdater介绍
- AtomicIntegerFieldUpdater:原子更新整形字段的更新器
AtomicIntegerFieldUpdater主要是对volatile修饰的Integer类型字段进行原子性的一系列操作
- AtomicLongFieldUpdater:原子更新长整形字段的更新器
AtomicLongFieldUpdater主要是对volatile修饰的Long类型字段进行原子性的一系列操作
由于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater常用API都差不多,唯一有区别的是数据类型不一样。AtomicIntegerFieldUpdater主要作用的是volatile修饰的Integer类型字段,AtomicLongFieldUpdater主要作用的是volatile修饰的Long类型字段。所以这里就以AtomicIntegerFieldUpdater为例进行记录
2.4.4.1 AtomicIntegerFieldUpdater常用API源码和注释
/**
* 用于创建一个新的AtomicIntegerFieldUpdater,它能够以原子方式更新给定类的指定名称的volatile字段
*/
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>
(tclass, fieldName, Reflection.getCallerClass());
}
/**
* 获取指定对象的volatile字段的当前值
*/
public abstract int get(T obj);
/**
* 以原子方式设置指定对象的volatile字段的值为新值
*/
public abstract void set(T obj, int newValue);
/**
* 如果当前指定对象的volatile字段的值与期望值一致,那么就进行原子性更新,并返回true,否则返回
* false
*/
public abstract boolean compareAndSet(T obj, int expect, int update);
/**
* 以原子方式设置指定对象的volatile字段值为新值,并返回该字段的旧值
*
*/
public int getAndSet(T obj, int newValue) {
int prev;
do {
prev = get(obj);
} while (!compareAndSet(obj, prev, newValue));
return prev;
}
/**
* 以原子的方式给指定对象的volatile字段加1,并返回旧值,可以理解为volatile字段++
*/
public int getAndIncrement(T obj) {
int prev, next;
do {
prev = get(obj);
next = prev + 1;
} while (!compareAndSet(obj, prev, next));
return prev;
}
/**
* 以原子的方式给指定对象的volatile字段减1,并返回旧值,可以理解为volatile字段--
*/
public int getAndDecrement(T obj) {
int prev, next;
do {
prev = get(obj);
next = prev - 1;
} while (!compareAndSet(obj, prev, next));
return prev;
}
/**
* 以原子的方式给指定对象的volatile字段加上delta,并返回旧值
*/
public int getAndAdd(T obj, int delta) {
int prev, next;
do {
prev = get(obj);
next = prev + delta;
} while (!compareAndSet(obj, prev, next));
return prev;
}
/**
* 以原子的方式给指定对象的volatile字段加1,并返回新值,可以理解为++volatile字段
*/
public int incrementAndGet(T obj) {
int prev, next;
do {
prev = get(obj);
next = prev + 1;
} while (!compareAndSet(obj, prev, next));
return next;
}
/**
* 以原子的方式给指定对象的volatile字段减1,并返回新值,可以理解为--volatile字段
*/
public int decrementAndGet(T obj) {
int prev, next;
do {
prev = get(obj);
next = prev - 1;
} while (!compareAndSet(obj, prev, next));
return next;
}
/**
* 以原子的方式给指定对象的volatile字段加上delta,并返回新值
*/
public int addAndGet(T obj, int delta) {
int prev, next;
do {
prev = get(obj);
next = prev + delta;
} while (!compareAndSet(obj, prev, next));
return next;
}
/**
* 使用给定函数,以原子方式更新指定对象的volatile字段值,并返回旧值,该函数接受当前值并计算一个
* 新的值
*/
public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get(obj);
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(obj, prev, next));
return prev;
}
/**
* 使用给定函数,以原子方式更新指定对象的volatile字段值,并返回新值,该函数接受当前值并计算一个
* 新的值
*/
public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get(obj);
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(obj, prev, next));
return next;
}
2.4.4.2 AtomicIntegerFieldUpdater常用API使用案例
public class Test {
private static final AtomicIntegerFieldUpdater<Product> fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Product.class, "count");
public static void main(String[] args) {
Product product = new Product();
fieldUpdater.set(product, 2);
int a = fieldUpdater.get(product);
System.out.println("get方法获取到的值:" + a + " product对象获取到的值:" + product.getCount()); //输出2 2
int b = fieldUpdater.getAndSet(product, 10);
System.out.println("设置新的值,返回旧值:" + b + " 新值" + product.getCount()); //输出 2 10
int c = fieldUpdater.getAndIncrement(product);
System.out.println("count++:" + c + " 加1以后得值:" + product.getCount());//输出10 11
int d = fieldUpdater.getAndDecrement(product);
System.out.println("count--:" + d + " 加1以后得值:" + product.getCount());//输出11 10
int e = fieldUpdater.getAndAdd(product, 10);
System.out.println("加10以后返回的旧值" + e + " 新值" + product.getCount()); // 输出 10 20
int f = fieldUpdater.incrementAndGet(product);
System.out.println("++count:" + f + " 加1以后得值:" + product.getCount()); //输出 21 21
int g = fieldUpdater.decrementAndGet(product);
System.out.println("--count:" + g + " 减1以后得值:" + product.getCount()); //输出 20 20
int h = fieldUpdater.addAndGet(product, 10);
System.out.println("加10以后返回的新值:" + h + " 新值:" + product.getCount());//输出 30 30
int i = fieldUpdater.getAndUpdate(product, x -> x + 10);
System.out.println("函数式相加返回旧值:" + i + "新值:" + product.getCount());// 输出 30 40
int j = fieldUpdater.updateAndGet(product, x -> x + 10);
System.out.println("函数式相加返回新值:" + j + "新值:" + product.getCount());// 输出 50 50
boolean flag = fieldUpdater.compareAndSet(product,50,60);
System.out.println("预计值一致,所以进行更新:"+flag+" 更新以后得值为:"+product.getCount()); //输出true 60
}
}
class Product {
volatile int count = 0;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
2.4.3 AtomicReferenceFieldUpdater介绍
AtomicReferenceFieldUpdater主要是对引用类型中被volatile修饰的字段进行原子性的操作
2.4.3.1 AtomicReferenceFieldUpdater常用API源码和注释
/**
* 构造方法,用于创建一个新的AtomicReferenceFieldUpdater,需要指定引用类型类
* 属性类型,字段名称
*/
public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
Class<W> vclass,
String fieldName) {
return new AtomicReferenceFieldUpdaterImpl<U,W>
(tclass, vclass, fieldName, Reflection.getCallerClass());
}
/**
* 获取指定对象的volatile字段的当前值
*/
public abstract V get(T obj);
/**
* 以原子方式设置指定对象的volatile字段的值为新值
*/
public abstract void set(T obj, V newValue);
/**
* 如果当前指定对象的volatile字段的值与期望值一致,那么就进行原子性更新,并返回true,否则返回
* false
*/
public abstract boolean compareAndSet(T obj, int expect, int update);
/**
* 以原子方式设置指定对象的volatile字段值为新值,并返回该字段的旧值
*/
public V getAndSet(T obj, V newValue) {
V prev;
do {
prev = get(obj);
} while (!compareAndSet(obj, prev, newValue));
return prev;
}
/**
* 使用给定函数,以原子方式更新指定对象的volatile字段值,并返回旧值,该函数接受当前值并计算一个
* 新的值
*/
public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) {
V prev, next;
do {
prev = get(obj);
next = updateFunction.apply(prev);
} while (!compareAndSet(obj, prev, next));
return prev;
}
/**
* 使用给定函数,以原子方式更新指定对象的volatile字段值,并返回新值,该函数接受当前值并计算一个
* 新的值
*/
public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) {
V prev, next;
do {
prev = get(obj);
next = updateFunction.apply(prev);
} while (!compareAndSet(obj, prev, next));
return next;
}
2.4.3.2 AtomicReferenceFieldUpdater常用API使用案例
public class Test {
private static final AtomicReferenceFieldUpdater<Product,Integer> fieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Product.class, Integer.class,"count");
public static void main(String[] args) {
Product product = new Product();
fieldUpdater.set(product, 2);
int a = fieldUpdater.get(product);
System.out.println("get方法获取到的值:" + a + " product对象获取到的值:" + product.getCount()); //输出2 2
int b = fieldUpdater.getAndSet(product, 10);
System.out.println("设置新的值,返回旧值:" + b + " 新值" + product.getCount()); //输出 2 10
int i = fieldUpdater.getAndUpdate(product, x -> x + 10);
System.out.println("函数式相加返回旧值:" + i + "新值:" + product.getCount());// 输出 10 20
int j = fieldUpdater.updateAndGet(product, x -> x + 10);
System.out.println("函数式相加返回新值:" + j + "新值:" + product.getCount());// 输出 30 30
boolean flag = fieldUpdater.compareAndSet(product,30,60);
System.out.println("预计值一致,所以进行更新:"+flag+" 更新以后得值为:"+product.getCount()); //输出true 60
}
}
class Product {
volatile Integer count = 0;
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
参考文档:
Java-Atomic-原子类-总结_java atomic-CSDN博客