java nio AtomicInteger源码分析
程序员文章站
2022-06-19 15:05:38
目录简介字段unsafe,valueOffset,value,2个构造函数方法get,set,lazySet,getAndSet,compareAndSet,weakCompareAndSet方法5个getAndXXX,5个XXXAndGet方法toString,4个XXXValue简介package java.util.concurrent.atomic;import java.util.function.IntUnaryOperator;import java.util...
目录
字段unsafe,valueOffset,value,2个构造函数
方法get,set,lazySet,getAndSet,compareAndSet,weakCompareAndSet
简介
package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
/**
* 一个可以自动更新的int值。看java.util.concurrent.atomic包描述原子变量属性的规范。
* AtomicInteger用于像原子递增计数器这样的应用程序,不能用作java.lang.Integer的替代品。
* 然而,这个类确实扩展了Number,允许处理基于数字的类的工具和实用程序进行统一访问。
*
* @since 1.5
* @author Doug Lea
*/
public class AtomicInteger extends Number implements java.io.Serializable
字段unsafe,valueOffset,value,2个构造函数
private static final long serialVersionUID = 6214790243416807050L;
// Unsafe构造器私有,且是一个单例模式,只能通过单例方法getUnsafe获得实例。可以使用指针偏移操作。
private static final Unsafe unsafe = Unsafe.getUnsafe();
// value的偏移量,用于unsafe对这个对象的对应的偏移量进行操作
private static final long valueOffset;
static {
try {
// 在静态初始化块中,通过反射的Field和Unsafe的objectFieldOffset,获得了value这个域相对于AtomicInteger对象的地址偏移量。
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// value域,是AtomicInteger对象的数据来源。
// 它被设置为volatile的,使得对value的操作结果都具有可见性。
//(注意,不保证原子性,比如value++这样的复合操作)
private volatile int value;
/**
* 使用给定的初始值创建一个新的AtomicInteger。
*
* @param initialValue the initial value
*/
public AtomicInteger(int initialValue) {
value = initialValue;
}
/**
* 使用初始值0创建一个新的AtomicInteger。
*/
public AtomicInteger() {
}
方法get,set,lazySet,getAndSet,compareAndSet,weakCompareAndSet
/**
* 获取当前值。
* 可见get/set没有加锁,但在多线程环境下,这两个函数也能保证线程安全。
* 因为return操作和赋值操作都是原子操作,所以两个函数都有原子性了,且volatile的value又使得对value的操作结果都具有可见性。
*
* @return the current value
*/
public final int get() {
return value;
}
/**
* 设置为给定值。
*
* @param newValue the new value
*/
public final void set(int newValue) {
value = newValue;
}
/**
* 最终设置为给定的值。
* 简单地说,lazySet使得程序执行变快了,但损失了可见性,
* 可见性直到有某个volatile write操作或同步操作才能恢复。
* volatile write操作会在该操作前添加 store-store内存屏障,在该操作之后添加 store-load内存屏障,但lazySet却省去了这个 store-load内存屏障。
* 这样,lazySet操作不会与任何先前的写操作重新排序,但可以与后续操作重新排序
* (lazySet操作因为重排序,可能排在了 它的后续操作的后面,自然也就不能保证其他线程可见了)。
*
* @param newValue the new value
* @since 1.6
*/
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
/**
* 原子地设置给定值并返回旧值。
*
* public final int getAndSetInt(Object o, long offset, int newValue) {
* int v;
* do {
* v = getIntVolatile(o, offset);
* } while (!compareAndSwapInt(o, offset, v, newValue));
* return v;
* }
* 上来就直接调用了Unsafe的操作。Unsafe的getAndSetInt逻辑,利用了 循环和CAS操作(compareAndSwap)和volatile变量,
* 使得更新操作不需要加锁就能完全,不过缺点是有可能会循环若干次才能成功。
* getIntVolatile使得线程总是获得变量的最新更新的值。
*
* compareAndSwapInt的前两个参数,根据指针o和指针偏移offset和int值所占字节数量4,可以读取出该对象中的value值是多少。
* 如果通过指针偏移发现 对象的value值 和 expected相同,那么将 对象的value值 设为 x,并返回true;
* 如果通过指针偏移发现 对象的value值 和 expected不相同,直接返回false。
*
* 而循环配合compareAndSwapInt,则使得,只有当对象的value值 在v = getIntVolatile(o, offset)和
* compareAndSwapInt(o, offset, v, newValue)的执行过程之间没有被其他线程修改的情况下
* (有可能执行前者之后,线程就被切换出去了,然后线程重新开始执行时,值已经被修改了),才会设置新值成功。
* 这个函数的缺点在于,有可能需要执行好多次循环,函数才能结束。
*
*
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
/**
* 如果当前值==期望值,则自动将值设置为给定的更新值。
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
// compareAndSet函数相比上一个函数,没有循环了,粒度变小了。它只是让你执行一次CAS操作,结果成功或者失败。
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* 如果当前值==期望值,则自动将值设置为给定的更新值。
*
* <p>可能会错误地失败,并且不提供排序保证,所以它很少是compareAndSet的合适的替代品。
*
* compareAndSet函数的weak版,但实现和compareAndSet一模一样,只能说,源码作者还没来得及写它的不同实现呢。
* 它可能会返回 虚假的失败,且不提供排序保证。
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
方法5个getAndXXX,5个XXXAndGet
/**
* 将当前值原子地加1。
*
* 这几个函数都调用unsafe.getAndAddInt。
*
* public final int getAndAddInt(Object o, long offset, int delta) {
* int v;
* do {
* v = getIntVolatile(o, offset);
* } while (!compareAndSwapInt(o, offset, v, v + delta));
* return v;
* }
* 方法和getAndSetInt差不多,区别再去新的值不在固定,而是v+delta
*
* 区别在于:
* getAndIncrement相当于i++,getAndAddInt刚好返回旧值。
* getAndDecrement相当于i--。
* getAndAdd相当于i += n,但是它却返回旧值。
*
* incrementAndGet相当于++i,返回 getAndAddInt的旧值再加1.
* decrementAndGet相当于--i,返回 getAndAddInt的旧值再减1.
* addAndGet相当于i += n,返回 getAndAddInt的旧值再加n。
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
/**
* 使当前值原子地递减一。
*
* @return the previous value
*/
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
/**
* 原子地将给定值添加到当前值。
*
* @param delta the value to add
* @return the previous value
*/
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
/**
* 将当前值原子地加1。
*
* @return the updated value
*/
public final int incrementAndGet() {
// 先得到原来的值,然后直接进行加减,然后返回
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
/**
* Atomically decrements by one the current value.
*
* @return the updated value
*/
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
/**
* Atomically adds the given value to the current value.
*
* @param delta the value to add
* @return the updated value
*/
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
/**
* 用应用给定函数的结果自动更新当前值,返回前一个值。
* 这个函数应该是没有副作用的,因为当尝试的更新由于线程间的争用而失败时,它可能会被重新应用。
*
* IntUnaryOperator是个函数式接口,看名字Unary就知道,它代表一个int的一元方程。
* 如果当你需要根据旧值来更新新值,且需要将更新的逻辑包含在函数式接口中时,就需要使用该函数。
* 注意,传入的IntUnaryOperator不应该有副作用,它应该只操作自己的局部变量。
* updateAndGet与前者的区别在于,它返回新值。
*
* @param updateFunction a side-effect-free function
* @return the previous value
* @since 1.8
*/
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
// 先得到当前的值,然后用updateFunction计算结果
//然后判断当前值是否是prev,是的话,设置为next
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* Atomically updates the current value with the results of
* applying the given function, returning the updated value. The
* function should be side-effect-free, since it may be re-applied
* when attempted updates fail due to contention among threads.
*
* @param updateFunction a side-effect-free function
* @return the updated value
* @since 1.8
*/
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
/**
* 将给定函数应用到当前值和给定值的结果自动更新当前值,并返回前一个值。
* 这个函数应该是无效果的,因为当由于线程间的争用而导致竞争更新失败时,它可能会被重新应用。
* 函数的第一个参数是当前值,第二个参数是给定的update。
*
* IntBinaryOperator是int的二元方程,所以还需要一个参数x。
*
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the previous value
* @since 1.8
*/
public final int getAndAccumulate(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* Atomically updates the current value with the results of
* applying the given function to the current and given values,
* returning the updated value. The function should be
* side-effect-free, since it may be re-applied when attempted
* updates fail due to contention among threads. The function
* is applied with the current value as its first argument,
* and the given update as the second argument.
*
* @param x the update value
* @param accumulatorFunction a side-effect-free function of two arguments
* @return the updated value
* @since 1.8
*/
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
方法toString,4个XXXValue
/**
* 返回当前值的字符串表示形式。
*
* @return the String representation of the current value
*/
public String toString() {
return Integer.toString(get());
}
/**
* 返回这个AtomicInteger的int值。
*/
public int intValue() {
return get();
}
/**
* 返回该AtomicInteger的值作为扩展原语转换后的long值。
*
* @jls 5.1.2 Widening Primitive Conversions
*/
public long longValue() {
return (long)get();
}
/**
* Returns the value of this {@code AtomicInteger} as a {@code float}
* after a widening primitive conversion.
* @jls 5.1.2 Widening Primitive Conversions
*/
public float floatValue() {
return (float)get();
}
/**
* Returns the value of this {@code AtomicInteger} as a {@code double}
* after a widening primitive conversion.
* @jls 5.1.2 Widening Primitive Conversions
*/
public double doubleValue() {
return (double)get();
}
本文地址:https://blog.csdn.net/xushiyu1996818/article/details/113936345