Java_UnSafeLockSupportAtomic
创始人
2024-05-26 08:49:35
0

sun.misc.Unsafe 使Java拥有了像C语言的指针一样操作内存空间的能力,一旦能够直接操作内存

Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,一旦能够直接操作内存,这也就意味着。 (1)不受jvm管理,也就意味着无法被GC,需要我们手动GC,稍有不慎就会出现内存泄漏。
(2)Unsafe的不少方法中必须提供原始地址(内存地址)和被替换对象的地址,偏移量要自己计算,一旦出现问题就是JVM崩溃级别的异常,会导致整个JVM实例崩溃,表现为应用程序直接crash掉。
(3)直接操作内存,也意味着其速度更快,在高并发的条件之下能够很好地提高效率。
因此,从上面三个角度来看,虽然在一定程度上提升了效率但是也带来了指针的不安全性。

使用方法

获取 Unsafe 实例

sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();

或者也可以使用反射或者Spring提供的UnsafeUtils工具类(如下图)获取到Unsafe实例

如何具体使用

普通读写

Unsafe 可以 读写 一个类的非static属性,即使这个属性是私有的。

public native int getInt(Object var1, long var2);public native void putInt(Object var1, long var2, int var4);...

volatile 读写

普通读写无法保证 可见性和有效性,而 volatile 就可以保证 可见性和有效性,但是 相对于 普通读写 更加 昂贵。

public native Object getObjectVolatile(Object var1, long var2);public native void putObjectVolatile(Object var1, long var2, Object var4);...

有序写入

有序写入 只保证有序性、不保证可见性,就是 一个线程写入不保证其它线程立即可见。
与 volatile 写入相比,有序写入 代价 相对较小。putOrderedXX写入不保证可见性,但是保证有序性,所谓有序性,就是保证指令不会重排序。

public native void putOrderedObject(Object var1, long var2, Object var4);public native void putOrderedInt(Object var1, long var2, int var4);public native void putOrderedLong(Object var1, long var2, long var4);

内存管理(直接操作内存)

//内存管理和操作
public native long allocateMemory(long var1);	//申请内存public native long reallocateMemory(long var1, long var3);	//调整内存public native void setMemory(Object var1, long var2, long var4, byte var6);public void setMemory(long var1, long var3, byte var5) {	//将给定内存块中的所有字节设置为固定值(通常是0)。this.setMemory((Object)null, var1, var3, var5);
}public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);	//内存复制 可以实现 对象浅拷贝public void copyMemory(long var1, long var3, long var5) {	//内存复制this.copyMemory((Object)null, var1, (Object)null, var3, var5);
}public native void freeMemory(long var1);	//释放内存

CAS 操作

CAS操作为java的锁机制提供一种新的方案,比如 AtomicInteger等类都是通过该方法实现的。compareAndSwap*方法是原子的,可以避免繁重的锁机制,提高代码效率。
CAS 还广泛应用于 乐观锁 比如 ReentrantLock、ConcurrentHashMap,ConcurrentLinkedQueue等都有用到CAS来实现乐观锁。

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

偏移量

Unsafe 还提供了获取 对象的指针,通过对 指针进行 偏移,不仅可以修改 指针指向的的数据(即使它们是私有的),甚至可以
找到JVM已经认定为 垃圾、可以进行回收的对象。

public native long staticFieldOffset(Field var1);	//获取静态属性Field在对象中的偏移量,读写静态属性时必须获取其偏移量public native long objectFieldOffset(Field var1);	//获取非静态属性Field在对象实例中的偏移量,读写对象的非静态属性时会用到这个偏移量public native Object staticFieldBase(Field var1);	//返回Field所在的对象
...

线程调度

通过park方法将线程进行挂起, 线程将一直阻塞到超时或中断条件出现。unpark方法可以终止一个挂起的线程,使其恢复正常。
整个并发框架中对线程的挂起操作被封装在LockSupport类中,LockSupport类中有各种版本park方法,但最终都调用了Unsafe.park()方法。

public native void unpark(Object var1);				//唤醒线程public native void park(boolean var1, long var2);	//挂起线程 ;park(false,0) 表示永不到期,一直挂起,直至被唤醒
//park的参数,表示挂起的到期时间,第一个如果是true,表示绝对时间,则var2为绝对时间值,单位是毫秒。第一个参数如果是false,表示相对时间,则var2为相对时间值,单位是纳秒。

类加载 及 非常规对象实例化

可以 动态地创建类、动态的创建一个匿名内部类、判断是否需要初始化一个类、 保证已经初始化过一个类;

public native boolean shouldBeInitialized(Class var1);	//判断是否需要初始化一个类public native void ensureClassInitialized(Class var1);	//保证已经初始化过一个类public native Class defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);	//方法定义一个类,用于动态地创建类public native Class defineAnonymousClass(Class var1, byte[] var2, Object[] var3);	//动态的创建一个匿名内部类

通常,我们通过new或反射来实例化对象,而Unsafe类提供的allocateInstance方法,可以直接生成对象实例,且无需调用构造方法和其他初始化方法;这在对象反序列化的时候会很有用,能够重建和设置final字段,而不需要调用构造方法。

public native Object allocateInstance(Class var1) throws InstantiationException;		//实例化一个 类实例 (非常规对象实例化)

内存屏障

public native void loadFence();		//保证在这个屏障之前的所有读操作都已经完成public native void storeFence();	//保证在这个屏障之前的所有写操作都已经完成public native void fullFence();		//保证在这个屏障之前的所有读写操作都已经完成

数组操作

arrayBaseOffset(获取数组第一个元素的偏移地址)与arrayIndexScale(获取数组中元素的增量地址)配合起来使用,
就可以定位数组中每个元素在内存中的位置。

由于Java的数组最大值为Integer.MAX_VALUE,使用Unsafe类的内存分配方法可以实现超大数组。实际上这样的数据就可以认为是C数组,因此需要注意在合适的时间释放内存。

//获取 数组 base 内存地址
public native int arrayBaseOffset(Class var1);
//返回 数组中元素与元素之间的偏移地址的增量
public native int arrayIndexScale(Class var1);

系统相关

//获取 本地指针的大小(单位是byte),通常值为4或者8。常量ADDRESS_SIZE就是调用此方法。
public native int addressSize();public native int pageSize();	内存页的大小,此值为2的幂次方。

源码解读 java8

package sun.misc;import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;public final class Unsafe {private static final Unsafe theUnsafe;					//单例 对象public static final int INVALID_FIELD_OFFSET = -1;public static final int ARRAY_BOOLEAN_BASE_OFFSET;public static final int ARRAY_BYTE_BASE_OFFSET;public static final int ARRAY_SHORT_BASE_OFFSET;public static final int ARRAY_CHAR_BASE_OFFSET;public static final int ARRAY_INT_BASE_OFFSET;public static final int ARRAY_LONG_BASE_OFFSET;public static final int ARRAY_FLOAT_BASE_OFFSET;public static final int ARRAY_DOUBLE_BASE_OFFSET;public static final int ARRAY_OBJECT_BASE_OFFSET;public static final int ARRAY_BOOLEAN_INDEX_SCALE;public static final int ARRAY_BYTE_INDEX_SCALE;public static final int ARRAY_SHORT_INDEX_SCALE;public static final int ARRAY_CHAR_INDEX_SCALE;public static final int ARRAY_INT_INDEX_SCALE;public static final int ARRAY_LONG_INDEX_SCALE;public static final int ARRAY_FLOAT_INDEX_SCALE;public static final int ARRAY_DOUBLE_INDEX_SCALE;public static final int ARRAY_OBJECT_INDEX_SCALE;public static final int ADDRESS_SIZE;//私有的构造方法private Unsafe() {}private static native void registerNatives();		//注册natives 方法,使得 Unsafe 类 可以操作 C 语言static {registerNatives();Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});	//给 Unsafe 注册 getUnsafe 方法theUnsafe = new Unsafe();	//实例化 theUnsafe 对象ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe.arrayBaseOffset(boolean[].class);ARRAY_BYTE_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);ARRAY_SHORT_BASE_OFFSET = theUnsafe.arrayBaseOffset(short[].class);ARRAY_CHAR_BASE_OFFSET = theUnsafe.arrayBaseOffset(char[].class);ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset(int[].class);ARRAY_LONG_BASE_OFFSET = theUnsafe.arrayBaseOffset(long[].class);ARRAY_FLOAT_BASE_OFFSET = theUnsafe.arrayBaseOffset(float[].class);ARRAY_DOUBLE_BASE_OFFSET = theUnsafe.arrayBaseOffset(double[].class);ARRAY_OBJECT_BASE_OFFSET = theUnsafe.arrayBaseOffset(Object[].class);ARRAY_BOOLEAN_INDEX_SCALE = theUnsafe.arrayIndexScale(boolean[].class);ARRAY_BYTE_INDEX_SCALE = theUnsafe.arrayIndexScale(byte[].class);ARRAY_SHORT_INDEX_SCALE = theUnsafe.arrayIndexScale(short[].class);ARRAY_CHAR_INDEX_SCALE = theUnsafe.arrayIndexScale(char[].class);ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale(int[].class);ARRAY_LONG_INDEX_SCALE = theUnsafe.arrayIndexScale(long[].class);ARRAY_FLOAT_INDEX_SCALE = theUnsafe.arrayIndexScale(float[].class);ARRAY_DOUBLE_INDEX_SCALE = theUnsafe.arrayIndexScale(double[].class);ARRAY_OBJECT_INDEX_SCALE = theUnsafe.arrayIndexScale(Object[].class);ADDRESS_SIZE = theUnsafe.addressSize();}//获取 unsafe 实例,只有由主类加载器加载的类才能调用这个方法@CallerSensitivepublic static Unsafe getUnsafe() {Class var0 = Reflection.getCallerClass();if (!VM.isSystemDomainLoader(var0.getClassLoader())) {throw new SecurityException("Unsafe");} else {return theUnsafe;}}//数组操作//获取 数组 base 内存地址public native int arrayBaseOffset(Class var1);//返回 数组中元素与元素之间的偏移地址的增量public native int arrayIndexScale(Class var1);//对象属性 读写 的操作方法public native int getInt(Object var1, long var2);public native void putInt(Object var1, long var2, int var4);public native Object getObject(Object var1, long var2);public native void putObject(Object var1, long var2, Object var4);public native boolean getBoolean(Object var1, long var2);public native void putBoolean(Object var1, long var2, boolean var4);public native byte getByte(Object var1, long var2);public native void putByte(Object var1, long var2, byte var4);public native short getShort(Object var1, long var2);public native void putShort(Object var1, long var2, short var4);public native char getChar(Object var1, long var2);public native void putChar(Object var1, long var2, char var4);public native long getLong(Object var1, long var2);public native void putLong(Object var1, long var2, long var4);public native float getFloat(Object var1, long var2);public native void putFloat(Object var1, long var2, float var4);public native double getDouble(Object var1, long var2);public native void putDouble(Object var1, long var2, double var4);// volatile 对象属性 读写 的操作方法public native Object getObjectVolatile(Object var1, long var2);public native void putObjectVolatile(Object var1, long var2, Object var4);public native int getIntVolatile(Object var1, long var2);public native void putIntVolatile(Object var1, long var2, int var4);public native boolean getBooleanVolatile(Object var1, long var2);public native void putBooleanVolatile(Object var1, long var2, boolean var4);public native byte getByteVolatile(Object var1, long var2);public native void putByteVolatile(Object var1, long var2, byte var4);public native short getShortVolatile(Object var1, long var2);public native void putShortVolatile(Object var1, long var2, short var4);public native char getCharVolatile(Object var1, long var2);public native void putCharVolatile(Object var1, long var2, char var4);public native long getLongVolatile(Object var1, long var2);public native void putLongVolatile(Object var1, long var2, long var4);public native float getFloatVolatile(Object var1, long var2);public native void putFloatVolatile(Object var1, long var2, float var4);public native double getDoubleVolatile(Object var1, long var2);public native void putDoubleVolatile(Object var1, long var2, double var4);//对象属性 有序写入 的操作方法public native void putOrderedObject(Object var1, long var2, Object var4);public native void putOrderedInt(Object var1, long var2, int var4);public native void putOrderedLong(Object var1, long var2, long var4);//内存管理和操作public native long allocateMemory(long var1);	//申请内存public native long reallocateMemory(long var1, long var3);	//调整内存public native void setMemory(Object var1, long var2, long var4, byte var6);public void setMemory(long var1, long var3, byte var5) {	//将给定内存块中的所有字节设置为固定值(通常是0)。this.setMemory((Object)null, var1, var3, var5);}public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);	//内存复制public void copyMemory(long var1, long var3, long var5) {	内存复制this.copyMemory((Object)null, var1, (Object)null, var3, var5);}public native void freeMemory(long var1);	//释放内存//cas 操作public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);// 偏移量 操作 方法/** @deprecated */@Deprecatedpublic int fieldOffset(Field var1) {return Modifier.isStatic(var1.getModifiers()) ? (int)this.staticFieldOffset(var1) : (int)this.objectFieldOffset(var1);}/** @deprecated */@Deprecatedpublic Object staticFieldBase(Class var1) {Field[] var2 = var1.getDeclaredFields();for(int var3 = 0; var3 < var2.length; ++var3) {if (Modifier.isStatic(var2[var3].getModifiers())) {return this.staticFieldBase(var2[var3]);}}return null;}public native long staticFieldOffset(Field var1);	//获取静态属性Field在对象中的偏移量,读写静态属性时必须获取其偏移量public native long objectFieldOffset(Field var1);	//获取非静态属性Field在对象实例中的偏移量,读写对象的非静态属性时会用到这个偏移量public native Object staticFieldBase(Field var1);	//返回Field所在的对象// 线程调度public native void unpark(Object var1);				//唤醒线程public native void park(boolean var1, long var2);	//挂起线程 ;park(false,0) 表示永不到期,一直挂起,直至被唤醒//park的参数,表示挂起的到期时间,第一个如果是true,表示绝对时间,则var2为绝对时间值,单位是毫秒。第一个参数如果是false,表示相对时间,则var2为相对时间值,单位是纳秒。//类加载 public native boolean shouldBeInitialized(Class var1);	//判断是否需要初始化一个类public native void ensureClassInitialized(Class var1);	//保证已经初始化过一个类public native Class defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);	//方法定义一个类,用于动态地创建类public native Class defineAnonymousClass(Class var1, byte[] var2, Object[] var3);	//动态的创建一个匿名内部类public native Object allocateInstance(Class var1) throws InstantiationException;		//实例化一个 类实例 (非常规对象实例化)//内存屏障public native void loadFence();		//保证在这个屏障之前的所有读操作都已经完成public native void storeFence();	//保证在这个屏障之前的所有写操作都已经完成public native void fullFence();		//保证在这个屏障之前的所有读写操作都已经完成//两个系统相关的方法://获取 本地指针的大小(单位是byte),通常值为4或者8。常量ADDRESS_SIZE就是调用此方法。public native int addressSize();public native int pageSize();	内存页的大小,此值为2的幂次方。//采集系统 负载数据public native int getLoadAverage(double[] var1, int var2);// Atomic 类实现相关public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;}public final long getAndAddLong(Object var1, long var2, long var4) {long var6;do {var6 = this.getLongVolatile(var1, var2);} while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));return var6;}public final int getAndSetInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var4));return var5;}public final long getAndSetLong(Object var1, long var2, long var4) {long var6;do {var6 = this.getLongVolatile(var1, var2);} while(!this.compareAndSwapLong(var1, var2, var6, var4));return var6;}public final Object getAndSetObject(Object var1, long var2, Object var4) {Object var5;do {var5 = this.getObjectVolatile(var1, var2);} while(!this.compareAndSwapObject(var1, var2, var5, var4));return var5;}}

LockSupport

使用例子

LockSupport.park()								//挂起线程;表示永不到期,一直挂起,直至被其它线程唤醒
LockSupport.park(blocker)						//被 blocker 挂起线程;表示永不到期,一直挂起,直至被其它线程唤醒
LockSupport.unpark(thread)						//唤醒 thread 
LockSupport.parkUntil(blocker, long deadline)	//被 blocker 挂起直到 deadline 时间戳,后 自动唤醒
LockSupport.parkUntil(long deadline)			//挂起直到 deadline 时间戳,后 自动唤醒
LockSupport.parkNanos(blocker, long nanos)		//被 blocker 挂起直到 nanos 毫秒,后 自动唤醒
LockSupport.parkNanos(long nanos)				//挂起直到 nanos 毫秒,后 自动唤醒

源码阅读

基本的线程锁

package java.util.concurrent.locks;
import sun.misc.Unsafe;
public class LockSupport {private LockSupport() {}	//私有的构造方法,不能被外部实例化private static final sun.misc.Unsafe UNSAFE;	private static final long parkBlockerOffset;	//Thread class parkBlocker 字段 内存地址;用于记录线程被谁阻塞的,用于线程监控和分析工具来定位原因的private static final long SEED;					//Thread class threadLocalRandomSeed 字段 内存地址private static final long PROBE;				//Thread class threadLocalRandomProbe 字段 内存地址private static final long SECONDARY;			//Thread class threadLocalRandomSecondarySeed 字段 内存地址static {try {UNSAFE = sun.misc.Unsafe.getUnsafe();Class tk = Thread.class;parkBlockerOffset = UNSAFE.objectFieldOffset(tk.getDeclaredField("parkBlocker"));	//获取 Thread class parkBlocker 字段 内存地址SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed"));	//获取 Thread class threadLocalRandomSeed 字段 内存地址PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomProbe"));	//获取 Thread class threadLocalRandomProbe 字段 内存地址SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSecondarySeed"));	//获取 Thread class threadLocalRandomSecondarySeed 字段 内存地址} catch (Exception ex) { throw new Error(ex); }}// 设置 线程t parkBlocker 字段为 arg ;这里只是记录 线程是被谁 阻塞的private static void setBlocker(Thread t, Object arg) {// Even though volatile, hotspot doesn't need a write barrier here.UNSAFE.putObject(t, parkBlockerOffset, arg);}// 唤醒 thread 线程public static void unpark(Thread thread) {if (thread != null)UNSAFE.unpark(thread);}// 记录被阻塞者,并一直阻塞 本线程, 清除 被阻塞者信息public static void park(Object blocker) {Thread t = Thread.currentThread();setBlocker(t, blocker);	//设置这个线程 被谁阻塞UNSAFE.park(false, 0L);	//一直阻塞这个线程setBlocker(t, null);	//设置这个线程 被阻塞者是 null;即清楚 被阻塞者}//记录被阻塞者,并阻塞 本线程 nanos 毫秒, 清除 被阻塞者信息public static void parkNanos(Object blocker, long nanos) {if (nanos > 0) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, nanos);setBlocker(t, null);}}	//记录被阻塞者,并阻塞 本线程 直到 deadline时间戳, 清除 被阻塞者信息public static void parkUntil(Object blocker, long deadline) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(true, deadline);setBlocker(t, null);}//或者 thread 被谁阻塞public static Object getBlocker(Thread t) {if (t == null)throw new NullPointerException();return UNSAFE.getObjectVolatile(t, parkBlockerOffset);}//一直阻塞 本线程public static void park() {UNSAFE.park(false, 0L);}//阻塞 本线程 nanos 毫秒public static void parkNanos(long nanos) {if (nanos > 0)UNSAFE.park(false, nanos);}//阻塞本线程,直到 deadline 时间戳public static void parkUntil(long deadline) {UNSAFE.park(true, deadline);}//产生本线程的 SecondarySeed 随机数 种子;为下一次生成随机数的因子static final int nextSecondarySeed() {int r;Thread t = Thread.currentThread();if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {r ^= r << 13;   // xorshiftr ^= r >>> 17;r ^= r << 5;}else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)r = 1; // avoid zeroUNSAFE.putInt(t, SECONDARY, r);return r;}
}

Atomic

基本类型

AtomicBoolean

AtomicInteger

package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;public class AtomicInteger extends Number implements java.io.Serializable {private static final Unsafe unsafe = Unsafe.getUnsafe();	//获取 unsafe 实例private volatile int value;									//注意 需要用 volatile 修饰;有序性和可见性private static final long valueOffset;						// 上面 value 在 内部布局中的 内存偏移量;用于原子操作static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));	//设置 value 在 内部布局中的 内存偏移量} catch (Exception ex) { throw new Error(ex); }}//无参构造方法public AtomicInteger() {}//有初始值构造方法public AtomicInteger(int initialValue) {value = initialValue;}//设置 value 值public final void set(int newValue) {value = newValue;}//获取 当前 value 值public final int get() {return value;}//有序性 设置 value 值public final void lazySet(int newValue) {unsafe.putOrderedInt(this, valueOffset, newValue);}//原子性 设置新值,返回 旧值public final int getAndSet(int newValue) {return unsafe.getAndSetInt(this, valueOffset, newValue);}//原子性 当 value是 expect时,设置为 updatepublic final boolean compareAndSet(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);}//原子性 +delta 操作,返回旧值public final int getAndAdd(int delta) {return unsafe.getAndAddInt(this, valueOffset, delta);}//原子性 + 1 操作,返回 新值public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 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;}//原子性 使用 updateFunction 值 更新 value 当前值,返回 更新前的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。public final int getAndUpdate(IntUnaryOperator updateFunction) {int prev, next;do {prev = get();next = updateFunction.applyAsInt(prev);} while (!compareAndSet(prev, next));return prev;}//原子性 使用 updateFunction 值 更新 value 当前值,返回 更新后的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。public final int updateAndGet(IntUnaryOperator updateFunction) {int prev, next;do {prev = get();next = updateFunction.applyAsInt(prev);} while (!compareAndSet(prev, next));return next;}//原子性 使用 updateFunction 值 更新 value 当前值,返回 更新前的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。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;}//原子性 使用 updateFunction 值 更新 value 当前值,返回 更新后的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。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;}
}

AtomicLong

引用类型

AtomicReference 原子更新引用类型,有ABA问题

AtomicStampedReference 原子更新引用类型(带时间戳,避免ABA问题)

AtomicReferenceFieldUpdater 原子更新引用类型的字段

AtomicMarkableReferce 原子更新带有标记位的引用类型 有ABA问题

数组类型

AtomicIntegerArray

AtomicLongArray

AtomicReferenceArray

字段类型

AtomicIntegerFieldUpdater

AtomicLongFieldUpdater

AtomicStampedFieldUpdater

JDK8新增原子类简介

DoubleAccumulator

LongAccumulator

DoubleAdder

LongAdder

总结

最后,简单总结下几种解决方案之间的区别:

特性Atomic变量volatile关键字Lock接口synchronized关键字
原子性可以保障无法保障可以保障可以保障
可见性可以保障可以保障可以保障可以保障
有序性无法保障一定程度保障可以保障可以保障

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...