内容简介:Java源码系列(7) -- AtomicInteger
一、前言
AtomicInteger基于CAS(Compare and Swap,比较并修改)的操作,主要实现乐观锁的思想。
对于传统的悲观锁来说,会假设线程并发非常重,每次修改数据,一定先100%确保自己进入安全区,再安心修改目标值。进而出现线程在竞争锁的过程中消耗大量时间在等待锁、加锁、解锁等操作上。(注:锁还可能涉及锁自旋、公平锁等知识点,而非简单暴力竞争)
相比之下的乐观锁,会假设只有自己一个线程修改目标值,先比较修改前的值是不是和自己的预期的一致,一致就修改并返回,不一致就放弃这次修改(CAS),并发起下一次的尝试,不会把时间用在加锁和解锁上。
虽然乐观锁看起来比悲观锁好很多,不过乐观锁主要用在单个值(Int,Float,Double)的并发修改上,而不是悲观锁对一个对象甚至是一个代码块的操作。
其次,若乐观锁对目标值修改操作次数远多于读取操作,那么CAS实际也会大量失败抵消CAS的优点,并演变成成多次重试失效。
说到CAS,需要了解的是这个能力并非由操作系统或JVM提供,而是CPU原生支持的。如果一个CPU不能保证CAS能力,那这个CPU的完全没有数据修改安全可言。
说回 AtomicInteger
,这类不能看见底层的运作,因为主要调用了 Unsafe
实现CAS。以后会写关于 Unsafe
的文章,敬请期待。
二、类签名
由于集成了 Number
,所以任何能接受 Number
类型的形参都能使用 AtomicInteger
public class AtomicInteger extends Number implements java.io.Serializable
三、静态初始化
在静态初始化块里面获取 value
的内存地址,这时的 value
内存地址已经开辟,但是没有被实例初始化。而静态初始化块是类初始化最早调用的,静态初始化安全由JVM来保证。
static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } }
四、数据成员
volatile保证value值的有序性和可见性,不保证原子性。原子性一般由synchronized或Lock来提供支持。
private volatile int value; // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset;
五、构造方法
// 用一个给定的整形值初始化一个AtomicInteger实例 public AtomicInteger(int initialValue) { value = initialValue; } // 初始化一个值为0的AtomicInteger实例 public AtomicInteger() { }
六、成员方法
// 获取当前的整形值,线程不安全 public final int get() { return value; } // 设置新的整形值,线程不安全 public final void set(int newValue) { value = newValue; } // 最终一定会把newValue设置成功 public final void lazySet(int newValue) { unsafe.putOrderedInt(this, valueOffset, newValue); } // 设置新的整形值,把返回上一个保存的值 public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); }
如果待修改的值和期待值相同,那就把待修改的值设置为update的值 伪代码: value == expect ? value = update; return isModified;
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } /** * Atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * * <p><a href="package-summary.html#weakCompareAndSet">May fail * spuriously and does not provide ordering guarantees</a>, so is * only rarely an appropriate alternative to {@code 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); }
// 先返回上一个值,然后再在原基础上自增1 public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } // 先返回上一个值,然后再在原基础上自减1 public final int getAndDecrement() { return unsafe.getAndAddInt(this, valueOffset, -1); } // 返回上一个值,并在原基础上加上指定值 // 伪代码: oldValue = value; value += delta; return oldValue; public final int getAndAdd(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta); } // 先自增,然后返回自增后的值 public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; } // 先自减,然后返回自减后的值 public final int decrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, -1) - 1; } // 先增加delta的值,然后返回增加后的值 public final int addAndGet(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta) + delta; }
七、 Java 8 Lambda支持
IntUnaryOperator -> This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
/** * Atomically updates the current value with the results of * applying the given function, returning the previous 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 previous value * @since 1.8 */ public final int getAndUpdate(IntUnaryOperator updateFunction) { int prev, next; do { 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; } /** * Atomically updates the current value with the results of * applying the given function to the current and given values, * returning the previous 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 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; }
八、参考链接
https://docs.oracle.com/javase/8/docs/api/java/util/function/IntUnaryOperator.html
https://docs.oracle.com/javase/8/docs/api/java/util/function/IntBinaryOperator.html
https://en.wikipedia.org/wiki/Compare-and-swap
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【源码阅读】AndPermission源码阅读
- ReactNative源码解析-初识源码
- 【源码阅读】Gson源码阅读
- Spring源码系列:BeanDefinition源码解析
- istio 源码 – Citadel 源码分析 (原创)
- istio 源码 – pilot 源码分析(原创)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ggplot2:数据分析与图形艺术
哈德利·威克姆 (Hadley Wickham) / 统计之都 / 西安交通大学出版社 / 2013-5-1 / CNY 46.00
中译本序 每当我们看到一个新的软件,第一反应会是:为什么又要发明一个新软件?ggplot2是R世界里相对还比较年轻的一个包,在它之前,官方R已经有自己的基础图形系统(graphics包)和网格图形系统(grid包),并且Deepayan Sarkar也开发了lattice包,看起来R的世界对图形的支持已经足够强大了。那么我们不禁要问,为什么还要发明一套新的系统? 设计理念 打个比......一起来看看 《ggplot2:数据分析与图形艺术》 这本书的介绍吧!
XML 在线格式化
在线 XML 格式化压缩工具
Markdown 在线编辑器
Markdown 在线编辑器