java源码-AtomicLong
开篇
AtomicLong位于java.util.concurrent.atomic包下,是java提供给的可以保证数据的原子性操作的一个类。和AtomicInteger的实现几乎是一致的。底层同样借助于unsafe实现原子操作。
据说sun.misc.Unsafe类库里面的 CAS算法,是通过用CPU指令来实现无锁自增,没仔细研究过所以暂时不展开。
AtomicLong类和构造器
AtomicLong类构造器有两个:
- 无参构造函数采用默认值初始化为0
- 有参数构造函数直接用initialValue来value的
AtomicLong类变量需要注意的两个点:
- AtomicLong的关键逻辑在于static代码快中通过unsafe接口初始化value的内存地址,后续直接通过内存地址进行操作。
- AtomicLong的value是用volatile进行修饰保证变量的可见性
public class AtomicLong extends Number implements java.io.Serializable { private static final long serialVersionUID = 1927816293512124184L; private static final Unsafe unsafe = Unsafe.getUnsafe(); // 保存AtomicLong中value的内存地址便于快速操作 private static final long valueOffset; static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); private static native boolean VMSupportsCS8(); // 获取value的内存地址的逻辑操作 static { try { valueOffset = unsafe.objectFieldOffset (AtomicLong.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile long value; // 以initialValue对value进行初始化 public AtomicLong(long initialValue) { value = initialValue; } // 以默认值0对value进行初始化 public AtomicLong() { } }
AtomicLong的get操作
AtomicLong类的get动作包括直接返回值和返回值后自增自减两类。在原子性的实现自增自减少的过程中通过unsafe. getAndAddLong()方法进行值的设置。
unsafe.getAndAddLong()方法的内部首先是获取旧的value并且通过compareAndSwapLong()方法保证在旧值v不变的基础上才能改为新值v+delta。
public final long getAndAddLong(Object o, long offset, long delta) { long v; do { v = getLongVolatile(o, offset); } while (!compareAndSwapLong(o, offset, v, v + delta)); return v; } ------------------------------------------------------------ public final long get() { return value; } public final long getAndSet(long newValue) { return unsafe.getAndSetLong(this, valueOffset, newValue); } public final long getAndIncrement() { return unsafe.getAndAddLong(this, valueOffset, 1L); } public final long getAndDecrement() { return unsafe.getAndAddLong(this, valueOffset, -1L); } public final long getAndAdd(long delta) { return unsafe.getAndAddLong(this, valueOffset, delta); } public final long getAndUpdate(LongUnaryOperator updateFunction) { long prev, next; do { prev = get(); next = updateFunction.applyAsLong(prev); } while (!compareAndSet(prev, next)); return prev; } 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; }
AtomicLong的set操作
AtomicLong类的set动作包括直接返回值和返回自增自减后的值两类。原子性实现自增自减是借助unsafe.getAndAddLong()方法实现的。
unsafe.getAndAddLong()方法的内部首先是获取旧的value并且通过compareAndSwapLong()方法保证在旧值v不变的基础上才能改为新值v+delta。
针对incrementAndGet()的实现细节,有一点比较有意思,unsafe.getAndAddLong(this, valueOffset, 1L) + 1L,因为unsafe.getAndAddLong返回的是旧值然后通过+delta实现最终的值。而此时对应value的值通过getAndAddLong()修改成了新值,也就说其实incrementAndGet()方法取的值并不是value的内存地址中对应的值。
public final long getAndAddLong(Object o, long offset, long delta) { long v; do { v = getLongVolatile(o, offset); } while (!compareAndSwapLong(o, offset, v, v + delta)); return v; } ------------------------------------------------------------ public final void set(long newValue) { value = newValue; } public final void lazySet(long newValue) { unsafe.putOrderedLong(this, valueOffset, newValue); } public final long incrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L; } public final long decrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L; } public final long addAndGet(long delta) { return unsafe.getAndAddLong(this, valueOffset, delta) + delta; } public final long updateAndGet(LongUnaryOperator updateFunction) { long prev, next; do { prev = get(); next = updateFunction.applyAsLong(prev); } while (!compareAndSet(prev, next)); return next; } 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; }
参考文章
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
C#多线程编程系列(五)- 使用任务并行库
原文: C#多线程编程系列(五)- 使用任务并行库 目录 1.1 简介 1.2 创建任务 1.3 使用任务执行基本的操作 1.4 组合任务 1.5 将APM模式转换为任务 1.6 将EAP模式转换为任务 1.7 实现取消选项 1.8 处理任务中的异常 1.9 并行运行任务 1.10 使用TaskScheduler配置任务执行 参考书籍 笔者水平有限,如果错误欢迎各位批评指正! 本系列首页链接:[C#多线程编程系列(一)- 简介 ] 1.1 简介 在之前的几个章节中,就线程的使用和多线程相关的内容进行了介绍。因为线程涉及到异步、同步、异常传递等问题,所以在项目中使用多线程的代价是比较高昂的,需要编写大量的代码来达到正确性和健壮性。 为了解决这样一些的问题,在.Net Framework 4.0中引入了一个关于一步操作的API。它叫做任务并行库(Task Parallel Library)。然后在.Net Framwork 4.5中对它进行了轻微的改进,本文的案例都是用最新版本的TPL库,而且我们还可以使用C# 5.0的新特性await/async来简化TAP编程,当然这是之后才介绍的。 ...
- 下一篇
mybatis mapper.xml 热部署
package com.guangeryi.mall.core.utils.mybatis; import com.guangeryi.mall.common.CommonConstant; import com.guangeryi.mall.core.utils.StringUtils; import org.apache.ibatis.binding.MapperProxyFactory; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.logging.log4j.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.Disposab...
相关文章
文章评论
共有0条评论来说两句吧...