atomicLong源码分析详解
atomicLong的字段和实例方法
源码分析
注意:源码分析都放在源码里面
package java.util.concurrent.atomic;
import java.util.function.LongUnaryOperator;
import java.util.function.LongBinaryOperator;
import sun.misc.Unsafe;
/**
一个long值可以用原子更新。 有关原子变量属性的描述,请参阅java.util.concurrent.atomic包规范。
一个AtomicLong用于诸如原子增量的序列号的应用中,不能用作Long的替代物 。 但是,该类确实扩展了Number ,以允许使用基于数字类的工具和实用程序的统一访问。
从以下版本开始:
1.5
另请参见:
Serialized Form
* @since 1.5
* @author Doug Lea
*/
public class AtomicLong extends Number implements java.io.Serializable {
private static final long serialVersionUID = 1927816293512124184L;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
private static native boolean VMSupportsCS8();
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicLong.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile long value;
/**
* 用给定的初始值创建一个新的AtomicLong
* @param initialValue initialValue - 初始值
*/
public AtomicLong(long initialValue) {
value = initialValue;
}
/**
* 创建一个新的AtomicLong,初始值为 0 。
*/
public AtomicLong() {
}
/**
* 获取当前值。
*
* @return 当前值
*/
public final long get() {
return value;
}
/**
* 设置为给定值。
*
* @param newValue newValue - 新价值
*/
public final void set(long newValue) {
value = newValue;
}
/**
* 最终设定为给定值。
*
* @param newValue newValue - 新价值
* @since 1.6
*/
public final void lazySet(long newValue) {
unsafe.putOrderedLong(this, valueOffset, newValue);
}
/**
* 这里抛出一个疑问?到底set()和lazySet()有什么区别?
* 1.首先set()是对volatile变量的一个写操作, 我们知道volatile的write
* 为了保证对其他线程的可见性会追加以下两个Fence(内存屏障)如下:
* 1.StoreStore 在intel cpu 不存在[写写]重排序
* 2.StoreLoad 这个是所有内存屏障里最耗性能的内存屏障相关参考Doug Lea大大的cookbook (http://g.oswego.edu/dl/jmm/cookbook.html)
* Doug Lea大大又说了, lazySet()省去了StoreLoad屏障, 只留下StoreStore
* 总结:set()和volatile具有一样的效果(能够保证内存可见性,能够避免指令重排序),
* 但是使用lazySet不能保证其他线程能立刻看到修改后的值(有可能发生指令重排序)。
* 简单点理解:lazySet比set()具有性能优势,但是使用场景很有限。
* 在网上没有找到lazySet和set的性能数据对比,
* 而且CPU的速度很快的,应用的瓶颈往往不在CPU,
* 而是在IO、网络、数据库等。对于并发程序要优先保证正确性,
* 然后出现性能瓶颈的时候再去解决。因为定位并发导致的问题,往往要比定位性能问题困难很多。
*/
/**
* 将原子设置为给定值并返回旧值。
* @param newValue newValue - 新的价值
* @return 以前的值
*/
public final long getAndSet(long newValue) {
return unsafe.getAndSetLong(this, valueOffset, newValue);
}
/**
* 如果当前值为 ==为预期值,则将该值原子设置为给定的更新值。
*
* @param expect expect - 预期值
* @param update update - 新值
* @return true如果成功
*/
public final boolean compareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
/**
* 如果当前值为== ,则将原值设置为给定的更新值。 May fail spuriously and does not provide ordering guarantees ,所以只是很少适合替代compareAndSet 。
*
* @param expect expect - 预期值
* @param update update - 新值
* @return true如果成功
*/
public final boolean weakCompareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
/**
* 原子上增加一个当前值。
* @return 以前的值
*/
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, valueOffset, 1L);
}
/**
* 原子减1当前值。
*
* @return 以前的值
*/
public final long getAndDecrement() {
return unsafe.getAndAddLong(this, valueOffset, -1L);
}
/**
* 将给定的值原子地添加到当前值。
*
* @param delta delta - 要添加的值
* @return 以前的值
*/
public final long getAndAdd(long delta) {
return unsafe.getAndAddLong(this, valueOffset, delta);
}
/**
* 原子上增加一个当前值。
*
* @return 更新的值
*/
public final long incrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}
/**
* 原子减1当前值。
*
* @return 更新的值
*/
public final long decrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
}
/**
* 将给定的值原子地添加到当前值。
*
* @param delta delta - 要添加的值
* @return 更新的值
*/
public final long addAndGet(long delta) {
return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
}
/**
* 用应用给定函数的结果原子更新当前值,返回上一个值。
* 该功能应该是无副作用的,因为尝试的更新由于线程之间的争用而失败时可能会被重新应用。
*
* @param updateFunction updateFunction - 无副作用的功能
* @return 以前的值
* @since 1.8
*/
public final long getAndUpdate(LongUnaryOperator updateFunction) {
long prev, next;
do {
prev = get();
next = updateFunction.applyAsLong(prev);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* 使用给定函数的结果原子更新当前值,返回更新的值。 该功能应该是无副作用的,因为尝试的更新由于线程之间的争用而失败时可能会被重新应用。
* @param updateFunction updateFunction - 无副作用的功能
* @return 更新的值
* @since 1.8
*/
public final long updateAndGet(LongUnaryOperator updateFunction) {
long prev, next;
do {
prev = get();
next = updateFunction.applyAsLong(prev);
} while (!compareAndSet(prev, next));
return next;
}
/**
* 使用给定函数应用给当前值和给定值的结果原子更新当前值,返回上一个值。
* 该功能应该是无副作用的,因为尝试的更新由于线程之间的争用而失败时可能会被重新应用。 该函数应用当前值作为其第一个参数,给定的更新作为第二个参数。
*
* @param x x - 更新值
* @param accumulatorFunction accumulatorFunction - 两个参数的无效副作用
* @return 以前的值
* @since 1.8
*/
public final long getAndAccumulate(long x,
LongBinaryOperator accumulatorFunction) {
long prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsLong(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
/**
* 使用将给定函数应用于当前值和给定值的结果原子更新当前值,返回更新后的值。
* 该功能应该是无副作用的,因为尝试的更新由于线程之间的争用而失败时可能会被重新应用。 该函数应用当前值作为其第一个参数,给定的更新作为第二个参数。
*
* @param x x - 更新值
* @param accumulatorFunction accumulatorFunction - 两个参数的无效副作用
* @return the updated value
* @since 1.8
*/
public final long accumulateAndGet(long x,
LongBinaryOperator accumulatorFunction) {
long prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsLong(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
/**
* Returns the String representation of the current value.
* @return the String representation of the current value
*/
public String toString() {
return Long.toString(get());
}
/**
* Returns the value of this {@code AtomicLong} as an {@code int}
* after a narrowing primitive conversion.
* @jls 5.1.3 Narrowing Primitive Conversions
*/
public int intValue() {
return (int)get();
}
/**
* Returns the value of this {@code AtomicLong} as a {@code long}.
*/
public long longValue() {
return get();
}
/**
* Returns the value of this {@code AtomicLong} 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 AtomicLong} as a {@code double}
* after a widening primitive conversion.
* @jls 5.1.2 Widening Primitive Conversions
*/
public double doubleValue() {
return (double)get();
}
}
总结:
- lz的Java8新特性掌握不好,看完这个我要去看看Java8的新特性了
- 下一步就对unsafe这个直接操作内存的类做一下分析