术语名称
|
英文
|
解释
|
缓存行
|
Cache line
|
缓存的最小操作单位
|
比较并交换
|
Compare and Swap
|
CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下在旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。
|
CPU流水线
|
CPU pipeline
|
CPU流水线的工作方式就象工业生产上的装配流水线,在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线,然后将一条X86指令分成5~6步后再由这些电路单元分别执行,这样就能实现在一个CPU时钟周期完成一条指令,因此提高CPU的运算速度。
|
内存顺序冲突
|
Memory order violation
|
内存顺序冲突一般是由假共享引起,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线。
|
在Atomic包里一共有12个类,四种原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新字段。Atomic包里的类基本都是使用Unsafe实现的包装类。
* AtomicBoolean:原子更新布尔类型。
* AtomicInteger:原子更新整型。
* AtomicLong:原子更新长整型。
* int addAndGet(int delta) :以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果
* boolean compareAndSet(int expect, int update) :如果输入的数值等于预期值,则以原子方式将该值设置为输入的值。
* int getAndIncrement():以原子方式将当前值加1,注意:这里返回的是自增前的值。
* void lazySet(int newValue):最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
* int getAndSet(int newValue):以原子方式设置为newValue的值,并返回旧值。
* AtomicIntegerArray:原子更新整型数组里的元素。
* AtomicLongArray:原子更新长整型数组里的元素。
* AtomicReferenceArray:原子更新引用类型数组里的元素。
* int addAndGet(int i, int delta):以原子方式将输入值与数组中索引i的元素相加。
* boolean compareAndSet(int i, int expect, int update):如果当前值等于预期值,则以原子方式将数组位置i的元素设置成update值。
3.原子更新引用类型
* AtomicReference:原子更新引用类型。
* AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
* AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子的更新一个布尔类型的标记位和引用类型。构造方法是AtomicMarkableReference(V initialRef, boolean initialMark)
4.原子更新字段类
* AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
* AtomicLongFieldUpdater:原子更新长整型字段的更新器。
* AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更数据和数据的版本号,可以解决使用CAS进行原子更新时,可能出现的ABA问题。
1 public class Unsafe { 2 // 单例对象 3 private static final Unsafe theUnsafe; 4 private Unsafe() { 5 } 6 @CallerSensitive 7 public static Unsafe getUnsafe() { 8 Class var0 = Reflection.getCallerClass(); 9 // 仅在引导类加载器`BootstrapClassLoader`加载时才合法 10 if(!VM.isSystemDomainLoader(var0.getClassLoader())) { 11 throw new SecurityException("Unsafe"); 12 } else { 13 return theUnsafe; 14 } 15 } 16 }
如何获取Unsafe实例?
1 public class UnsafeInstance { 2 3 public static Unsafe reflectGetUnsafe() { 4 try { 5 Field field = Unsafe.class.getDeclaredField("theUnsafe"); 6 field.setAccessible(true); 7 return (Unsafe) field.get(null); 8 } catch (Exception e) { 9 e.printStackTrace(); 10 } 11 return null; 12 } 13 }
1.内存操作
1 //分配内存, 相当于C++的malloc函数 2 public native long allocateMemory(long bytes); 3 //扩充内存 4 public native long reallocateMemory(long address, long bytes); 5 //释放内存 6 public native void freeMemory(long address); 7 //在给定的内存块中设置值 8 public native void setMemory(Object o, long offset, long bytes, byte value); 9 //内存拷贝 10 public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); 11 //获取给定地址值,忽略修饰限定符的访问限制。与此类似操作还有: getInt,getDouble,getLong,getChar等 12 public native Object getObject(Object o, long offset); 13 //为给定地址设置值,忽略修饰限定符的访问限制,与此类似操作还有: putInt,putDouble,putLong,putChar等 14 public native void putObject(Object o, long offset, Object x); 15 public native byte getByte(long address); 16 //为给定地址设置byte类型的值(当且仅当该内存地址为allocateMemory分配 时,此方法结果才是确定的) 17 public native void putByte(long address, byte x);
* 对垃圾回收停顿的改善。由于堆外内存是直接受操作系统管理而不是JVM,所以当我们使用堆外内存时,即可保持较小的堆内内存规模。从而在GC时减少回收停顿对于应用的影响。
* 提升程序I/O操作的性能。通常在I/O通信过程中,会存在堆内内存到堆外内存的数据拷贝操作,对于需要频繁进行内存间数据拷贝且生命周期较短的暂存数据,都建议存储到堆外内存。
典型应用
2.CAS相关
1 /** 2 * CAS 3 * @param o 包含要修改field的对象 4 * @param offset 对象中某field的偏移量 5 * @param expected 期望值 6 * @param update 更新值 7 * @return true | false 8 */ 9 public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5); 10 11 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5); 12 13 public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
典型应用
3.线程调度
1 //取消阻塞线程 2 public native void unpark(Object thread); 3 //阻塞线程 4 public native void park(boolean isAbsolute, long time); 5 //获得对象锁(可重入锁) 6 @Deprecated 7 public native void monitorEnter(Object o); 8 //释放对象锁 9 @Deprecated 10 public native void monitorExit(Object o); 11 //尝试获取对象锁 12 @Deprecated 13 public native boolean tryMonitorEnter(Object o);
方法park、unpark即可实现线程的挂起与恢复,将一个线程进行挂起是通过park方法实现的,调用park方法后,线程将一直阻塞直到超时或者中断等条件出现;unpark可以终止一个挂起的线程,使其恢复正常。
典型应用
1 //内存屏障,禁止load操作重排序。屏障前的load操作不能被重排序到屏障后,屏障后的load操作不能被重排序到屏障前 2 public native void loadFence(); 3 //内存屏障,禁止store操作重排序。屏障前的store操作不能被重排序到屏障后,屏障后的store操作不能被重排序到屏障前 4 public native void storeFence(); 5 //内存屏障,禁止load、store操作重排序 6 public native void fullFence();
典型应用
原文:https://www.cnblogs.com/Mapi/p/14417824.html