Java原子操作
Java 原子类包括以下几种类型: AtomicBoolean:原子布尔类型,提供原子性的读取和设置操作。 AtomicInteger:原子整数类型,提供原子性的读取、设置、增加、减少、比较和交换操作。 AtomicLong:原子长整型,提供原子性的读取、设置、增加、减少、比较和交换操作。 AtomicIntegerArray:原子整数数组,提供原子性的数组元素读取、设置、增加、减少、比较和交换操作。 AtomicLongArray:原子长整型数组,提供原子性的数组元素读取、设置、增加、减少、比较和交换操作。 AtomicReference:原子引用类型,提供原子性的引用读取和设置操作。 AtomicStampedReference:带时间戳的原子引用类型,可以避免 ABA 问题。 AtomicMarkableReference:带标记位的原子引用类型,可以用于标记某个对象是否被删除等。 AtomicInteger 原理
AtomicInteger 是 Java 并发包中提供的一个原子类,用于实现原子性操作的整型变量。它的原理是利用了 CPU 提供的原子性操作指令,通过 CAS(Compare and Swap)算法实现原子性操作。
CAS 算法是一种无锁算法,通过比较当前内存地址的值与期望值是否相等,如果相等则将新的值写入该内存地址,否则不做任何操作。CAS 算法的基本操作包括三个参数:内存地址 V、期望值 A 和新值 B。如果 V 的值等于 A,则将 V 的值修改为 B,否则不做任何操作。CAS 算法的实现通常由硬件层面提供支持,可以保证原子性操作的高效性和正确性。
在 AtomicInteger 类中,原子性操作的实现就是利用了 CAS 算法。例如,对于 AtomicInteger 的 incrementAndGet() 方法,其实现大致如下:
1. 获取当前 AtomicInteger 的值 value。
2. 将 value 和 1 相加,得到新的值 newValue。
3. 利用 CAS 算法,将内存地址 V 的值与期望值 A(即原来的 value)比较,如果相等,则将 V 的值修改为新值 B(即 newValue),并返回修改后的值。
4. 如果 CAS 操作失败,则重新执行步骤 1 到 3,直到 CAS 操作成功为止。
通过这种方式,AtomicInteger 类可以实现原子性的自增、自减、比较和交换等操作,避免了多线程环境下的数据竞争问题。同时,由于 CAS 算法是一种无锁算法,因此可以避免了锁的开销和竞争带来的性能损失,具有较好的性能和可伸缩性。AutomicInteger 源码详解
AtomicInteger 是 Java 中用于实现原子性操作的类之一,其源码主要包含以下几个方面:value:AtomicInteger 的内部整型变量,使用 volatile 关键字来保证多线程环境下的可见性和有序性。private volatile int value;AtomicInteger():AtomicInteger 的无参构造方法,用于初始化 value 的值为 0。public AtomicInteger() { this(0); }AtomicInteger(int initialValue):AtomicInteger 的有参构造方法,用于初始化 value 的值为指定的初始值。public AtomicInteger(int initialValue) { value = initialValue; }get():获取当前 AtomicInteger 的值。public final int get() { return value; }set(int newValue):设置当前 AtomicInteger 的值为指定的新值。public final void set(int newValue) { value = newValue; }compareAndSet(int expect, int update):比较并设置当前 AtomicInteger 的值。如果当前值等于期望值 expect,则将当前值修改为新值 update,返回 true;否则不做任何操作,返回 false。public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }getAndSet(int newValue):设置当前 AtomicInteger 的值为指定的新值,并返回修改前的值。public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); }getAndIncrement():原子性自增操作,将当前 AtomicInteger 的值加 1,并返回自增前的值。public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); }getAndDecrement():原子性自减操作,将当前 AtomicInteger 的值减 1,并返回自减前的值。public final int getAndDecrement() { return unsafe.getAndAddInt(this, valueOffset, -1); }incrementAndGet():原子性自增操作,将当前 AtomicInteger 的值加 1,并返回自增后的值。public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; }decrementAndGet():原子性自减操作,将当前 AtomicInteger 的值减 1,并返回自减后的值。public final int decrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, -1) - 1; }
以上是 AtomicInteger 类的主要方法和字段,它们都是基于 CAS(Compare and Swap)算法实现的,保证了在多线程环境下的原子性操作。原子数组AtomicIntegerArray 原理
AtomicIntegerArray 是 Java 并发包中提供的一个原子操作类,可以实现对整型数组的原子操作。它的原理是通过底层调用 sun.misc.Unsafe 类的方法来实现对数组元素的 CAS 操作,从而保证多线程并发访问时的数据安全。
具体来说,AtomicIntegerArray 中的核心方法包括 get、set、getAndAdd、getAndIncrement、getAndDecrement、getAndSet 和 compareAndSet 等。其中,get 和 set 方法分别用于获取和设置指定下标的数组元素的值,它们不涉及原子操作;getAndAdd、getAndIncrement、getAndDecrement 和 getAndSet 方法则是进行原子操作的方法,它们都是通过 do-while 循环不断尝试 CAS 操作,直到成功为止,然后返回旧值;compareAndSet 方法是进行原子操作的核心方法,它使用 Unsafe 类的 compareAndSwapInt() 方法来实现 CAS 操作,如果操作成功则返回 true,否则返回 false。
为了实现对数组元素的 CAS 操作,AtomicIntegerArray 中使用了 sun.misc.Unsafe 类的一些方法,包括 compareAndSwapInt、arrayBaseOffset 和 arrayIndexScale 等。其中,compareAndSwapInt 方法是用于实现 CAS 操作的方法,它的作用是比较指定位置的数组元素的值是否等于期望值,如果相等则将其设为新值,返回操作是否成功的布尔值;arrayBaseOffset 和 arrayIndexScale 方法则是用于计算数组元素的地址偏移量的方法,它们分别返回数组在内存中的基地址和元素之间的偏移量,从而可以计算出数组元素在内存中的地址偏移量,方便进行 CAS 操作。
总之,AtomicIntegerArray 的原理是通过底层调用 Unsafe 类的方法实现对整型数组的原子操作,从而保证多线程并发访问时的数据安全。 AtomicIntegerArray 源码解析public class AtomicIntegerArray implements java.io.Serializable { private static final long serialVersionUID = 2862133569453604235L; // 数组元素,使用 volatile 修饰以保证内存可见性 private final int[] array; // 构造方法,将传入的数组复制一份作为 AtomicIntegerArray 的数组元素 public AtomicIntegerArray(int length) { array = new int[length]; } // 构造方法,将传入的数组复制一份作为 AtomicIntegerArray 的数组元素 public AtomicIntegerArray(int[] array) { this.array = array.clone(); } // 获取指定下标的数组元素的值 public final int get(int i) { return array[i]; } // 设置指定下标的数组元素的值 public final void set(int i, int newValue) { array[i] = newValue; } // 获取指定下标的数组元素的值,并将其加上指定的 delta 值 public final int getAndAdd(int i, int delta) { // do-while 循环,直到 CAS 成功为止 int oldValue; do { oldValue = get(i); // 获取当前值 } while (!compareAndSet(i, oldValue, oldValue + delta)); // 比较并交换,如果失败则继续循环 return oldValue; // 返回旧值 } // 获取指定下标的数组元素的值,并将其加上 1 public final int getAndIncrement(int i) { return getAndAdd(i, 1); } // 获取指定下标的数组元素的值,并将其减去 1 public final int getAndDecrement(int i) { return getAndAdd(i, -1); } // 获取指定下标的数组元素的值,并将其设为指定的 newValue 值 public final int getAndSet(int i, int newValue) { // do-while 循环,直到 CAS 成功为止 int oldValue; do { oldValue = get(i); // 获取当前值 } while (!compareAndSet(i, oldValue, newValue)); // 比较并交换,如果失败则继续循环 return oldValue; // 返回旧值 } // 比较指定下标的数组元素的值是否等于 expect,如果相等则将其设为 update public final boolean compareAndSet(int i, int expect, int update) { // 使用 unsafe.compareAndSwapInt() 方法实现 CAS 操作 return unsafe.compareAndSwapInt(array, byteOffset(i), expect, update); } // 获取数组元素在数组中的偏移量(即下标乘以元素大小) private static int byteOffset(int i) { return i << 2; // 相当于 i * 4 } // 获取 Unsafe 实例,用于实现 CAS 操作 private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); private static final long base = unsafe.arrayBaseOffset(int[].class); private static final long shift; static { int scale = unsafe.arrayIndexScale(int[].class); if ((scale & (scale - 1)) != 0) { throw new Error("data type scale not a power of two"); } shift = 31 - Integer.numberOfLeadingZeros(scale); } // 计算数组元素在内存中的地址偏移量 private static long calcLongOffset(int i) { return ((long) i << shift) + base; } }原子更新器AtomicLongFieldUpdater原理
AtomicLongFieldUpdater 是 Java 并发包中提供的一种工具类,用于实现对某个对象的 long 类型字段的原子操作。它可以让我们利用原子性操作实现对共享变量的高效访问,避免使用锁机制带来的性能损耗和死锁问题。
AtomicLongFieldUpdater 的实现原理是利用反射机制和 CAS(Compare-And-Swap)操作实现对共享变量的原子操作。具体来说,AtomicLongFieldUpdater 类通过反射机制访问对象的 long 类型字段,然后调用 Unsafe 类的 compareAndSwapLong 方法,实现对字段的原子操作。
CAS 操作是一种原子性操作,它可以保证多线程并发访问时的数据安全。CAS 操作的基本思想是,先获取共享变量的当前值,然后比较这个值是否等于期望值,如果相等,则将共享变量的值设为新值,否则不做任何操作。如果多个线程同时尝试对同一个共享变量进行 CAS 操作,只有一个线程能够成功,其他线程将会失败,需要重新尝试。
AtomicLongFieldUpdater 利用 CAS 操作实现了对共享变量的原子操作。例如,可以通过 AtomicLongFieldUpdater 对某个类的 long 类型字段进行原子操作,而不需要使用锁机制。
需要注意的是,使用 AtomicLongFieldUpdater 操作字段时,要求该字段必须是 volatile 类型的,否则可能会出现数据不一致的问题。
总之,AtomicLongFieldUpdater 是 Java 并发包中提供的一种工具类,它利用反射机制和 CAS 操作实现对某个对象的 long 类型字段的原子操作,可以提高多线程并发访问的性能和安全性。AtomicLongFieldUpdater源码分析public abstract class AtomicLongFieldUpdater { // 获取一个对象的 long 类型字段的值 public abstract long get(T obj); // 设置一个对象的 long 类型字段的值 public abstract void set(T obj, long newValue); // 比较并设置一个对象的 long 类型字段的值,如果当前值等于期望值,则设置为新值 public abstract boolean compareAndSet(T obj, long expect, long update); // 弱化版的 compareAndSet,不保证成功设置字段值,但执行效率更高 public abstract boolean weakCompareAndSet(T obj, long expect, long update); // 对一个对象的 long 类型字段进行增加操作,并返回新的值 public abstract long getAndAdd(T obj, long delta); // 对一个对象的 long 类型字段进行增加操作,并返回新的值 public abstract long addAndGet(T obj, long delta); // 创建一个 AtomicLongFieldUpdater 实例,用于更新指定类的指定字段 public static AtomicLongFieldUpdater newUpdater(Class tclass, String fieldName) { // 参数校验 if (tclass == null || fieldName == null) { throw new NullPointerException(); } // 获取字段的反射对象 final Field field; try { field = tclass.getDeclaredField(fieldName); if (!Modifier.isVolatile(field.getModifiers())) { throw new IllegalArgumentException("Must be volatile"); } Class<?> fieldType = field.getType(); if (fieldType != long.class) { throw new IllegalArgumentException("Must be long type"); } } catch (Exception ex) { throw new RuntimeException(ex); } // 创建 AtomicLongFieldUpdaterImpl 实例 return new AtomicLongFieldUpdaterImpl(field); } }class AtomicLongFieldUpdaterImpl extends AtomicLongFieldUpdater { // 字段的偏移量 private final long offset; // 构造方法,通过反射获取字段的偏移量 AtomicLongFieldUpdaterImpl(Field field) { // 参数校验 if (!Modifier.isVolatile(field.getModifiers())) { throw new IllegalArgumentException("Must be volatile"); } Class<?> fieldType = field.getType(); if (fieldType != long.class) { throw new IllegalArgumentException("Must be long type"); } // 获取字段的偏移量 this.offset = unsafe.objectFieldOffset(field); } // 获取一个对象的 long 类型字段的值 public long get(T obj) { return unsafe.getLongVolatile(obj, offset); } // 设置一个对象的 long 类型字段的值 public void set(T obj, long newValue) { unsafe.putLongVolatile(obj, offset, newValue); } // 比较并设置一个对象的 long 类型字段的值,如果当前值等于期望值,则设置为新值 public boolean compareAndSet(T obj, long expect, long update) { return unsafe.compareAndSwapLong(obj, offset, expect, update); } // 弱化版的 compareAndSet,不保证成功设置字段值,但执行效率更高 public boolean weakCompareAndSet(T obj, long expect, long update) { return unsafe.compareAndSwapLong(obj, offset, expect, update); } // 对一个对象的 long 类型字段进行增加操作,并返回新的值 public long getAndAdd(T obj, long delta) { long current, next; do { current = get(obj); next = current + delta; } while (!compareAndSet(obj, current, next)); return current; } // 对一个对象的 long 类型字段进行增加操作,并返回新的值 public long addAndGet(T obj, long delta) { long current, next; do { current = get(obj); next = current + delta; } while (!compareAndSet(obj, current, next)); return next; } }
AtomicLongFieldUpdater 是一个抽象类,用于实现对某个对象的 long 类型字段的原子操作。该类的主要方法包括 get、set、compareAndSet、weakCompareAndSet、addAndGet 和 getAndAdd 等,通过反射机制和 Unsafe 类实现对共享变量的原子操作。
小结:
小心这些原子类中的set和get方法。没有使用cas就不保证原子性了,只能保证可见性和有序性。
业绩持续高增长的优质股名单出炉,1800亿锂电巨头大涨,20倍超级慢牛股现身(名单)数据是个宝数据宝炒股少烦恼优质股补涨机会一触即发。早盘各主要指数强势震荡,船舶运输服务煤炭等板块均涨超1。概念板块方面,航运概念固态电池钠电池概念等均涨逾1。个股赚钱效应依旧凸显,
蓝焰控股2022年前三季度净利润4。59亿元同比增长99。46中证智能财讯蓝焰控股(000968)10月20日披露2022年第三季度报告。2022年前三季度,公司实现营业总收入18。39亿元,同比增长31。98归母净利润4。59亿元,同比增长
人到中年不劝人,因为好言劝不住该死的鬼人到中年不劝人,因为,无论你说什么,对别人而言无非都是些废话,屁话,没有用的话,被当做耳旁风的话。是的,渐渐地,我开始相信人是没法被改变的。往好听了说,叫江山易改,本性难移而直白点
秋风起,秋忆浓头条创作挑战赛阵阵秋风起秋色意浓浓农民们扎起了粮囤玉米金灿灿池塘的水面铺满了密密麻麻的菱角田间地头人们挥洒着汗水收着花生棉花唱着丰收的美妙的进行曲闲暇的时候拆洗衣物针线穿飞秋意在空
千亿私募巨头最新发声中国基金报记者吴君实习生余洋尽管近期沪指在3000点附近震荡,但头部私募纷纷表达了对市场投资机会的看好。千亿私募景林资产发声,之前的极端预期在边际上扭转,市场即将寻找业绩底部,政策
这些潜规则你一定要懂得一二1长时间不联系的朋友,有事直接说事,不要总问别人在不在。不说什么事情,别人怎么回答?万一你借钱怎么办,借钱那肯定不在。2原则上不行,那就是可以。按道理说可以,那就是不行。3千万不要
人民日报金句摘抄(105)1。历史的进程有多么波澜壮阔,所产生的影响就有多么广泛深远。2。建设生态文明,关系人民福祉,关乎民族未来。3。回望过往的奋斗路,坚定的历史自信,让我们荡开层云千叠,踏平坎坷成大道。
独处是一个人提升自我的时候01hr很多人都做着朝九晚五的工作,但是我的工作限制了我的日常,一般别人休息的时候,我可能在上班,我在上班的时候,别人可能在休息。我和别人的差异化就这样拉开了,记得刚开始上班的时候
如果一个人伤天害理,无恶不做,恶贯满盈,早晚会得到报应天道轮回,苍天饶过谁的意思是善恶到头终有报应。做的好事坏事老天都记着账呢,别以为一时不报就觉得没人管你,等到轮回结算的时候,就明白老天不会放过一个坏人也不会忘记酬劳一个好人。我认为
精神学习VS技术学习人生没有追求,活着就是一种煎熬。成功的人,未必会能感到持久的幸福但是拥有持久的幸福感的人,必须不断追求成功。只不过,有的人认为挣很多钱是成功,有的人认为迎娶心上人是成功,有的人认为
0459转机萨拉罗布奥黑根(1)第一章成功就是知道你自己是谁1每天早上起床时,你可以问自己一个问题你最喜欢做的是什么?不要让别人告诉你成功的定义。成功就是知道自己是谁,知道自己与生俱来的天分是什么,知道什么能打动