概述

Unsafesun.misc 包下的一个类,主要提供一些用于执行低级别:
11. Unsafe - 图1

理解对象中的偏移地址

在说明 Unsafe API 之前,我们先来理解什么是 对象中的偏移地址。

对象在堆中基本内存结构

作为一个 Javaer 都知道对象是存储在堆中的,可是在堆中也肯定由某种数据结构来表示。下图就是 Java 对象在堆中的基本内存结构:
image.png
Java 对象在堆中的结构可大致分为三部分,分别是

  • 对象头。
  • 对象/数组实际数据。
  • 对齐填充。

对于 64 位计算机而言,对象头总共占用 16 字节空间。而对于 32 位计算机,对象头总共占用 8 字节。

Unsafe API

  1. // peek 和 poke 操作。这部分是适用于Java堆的对象,并不适用于打包数组元素上。
  2. // They will not work on elements of packed arrays.
  3. // Java 基本数据类型: byte、short、int、long、float、double、boolean、char
  4. /**
  5. * 从给定的Java变量中获取一个值。更具体的说,从给定对象o中以给定偏移量或
  6. * (如果o为空)从数值为给定偏移量的内存地址中获取字段或数组元素。
  7. *
  8. * 除非满足以下情况之一,否则结果将会是不确定的:
  9. * ① 偏移量offset是从某个Java字段的objectFieldOffset获得的,而o所引用的对象是与该字段的类兼容的类。
  10. * ② 偏移量offset和对象引用o(null或非null)分别通过 staticFieldOffset 和 staticFieldBase 从某些
  11. * Java 字段的反射Field表示中获得的。
  12. * ③ 假如o引用的对象是数组,偏移量是公式B+N*S所返回的整数,表示第N个元素偏移量。
  13. * B: 表示arrayBaseOffset()函数求得的值。
  14. * N: 数组的有效索引。
  15. * S: 表示arrayIndexScale()函数求得的值。表示某个数据类型占用多少字节。比如 arrayIndexScale(int[].class)=4。
  16. *
  17. * 如果以上三种情况有一个成立,则该函数调用会执行正确的语义: 该调用引用特定的Java变量(字段或数组元素)。
  18. * 但是,如果该变量实际上并非由对应函数所返回,则结果将是不确定的。
  19. *
  20. * 由于此方法通过两个参数引用一个变量,因此它实际上为 Java 变量提供了一个「双寄存器寻址模式」。
  21. * 当参数o==null时,此方法将其偏移量用作「绝对地址」。与 getInt(long address) 函数相同,它为非 java
  22. * 变量提供单寄存器寻址模式。然而,由于 Java 变量在内存中的布局可能与非Java对象不同,
  23. * 程序员不应假定这两个寻址模式永远是等效的。
  24. * 另外,不能将双寄存器寻址模式的偏移量和单寄存器寻址模式中使用的「长度」混淆。
  25. *
  26. * @param o 驻留在Java堆中的对象
  27. * @param offset 如果o != null,表示驻留在Java堆中的对象的位置。
  28. * 如果o == null,表示绝对地址
  29. */
  30. public native int getInt(Object o, long offset);
  31. /**
  32. * 将值存储到给定的 Java 变量中。
  33. * 前两个参数可以完全按照 getInt(Object, long) 来理解,表示引用特定的Java变量(字段或数组元素)。
  34. * 将给定的值存储在该变量中。
  35. * 变量必须与方法参数x的类型相同。
  36. */
  37. public native void putInt(Object o, long offset, int x);
  38. public native boolean getBoolean(Object o, long offset);
  39. public native void putBoolean(Object o, long offset, boolean x);
  40. public native byte getByte(Object o, long offset);
  41. public native void putByte(Object o, long offset, byte x);
  42. public native short getShort(Object o, long offset);
  43. public native void putShort(Object o, long offset, short x);
  44. public native char getChar(Object o, long offset);
  45. public native void putChar(Object o, long offset, char x);
  46. public native long getLong(Object o, long offset);
  47. public native void putLong(Object o, long offset, long x);
  48. public native float getFloat(Object o, long offset);
  49. public native void putFloat(Object o, long offset, float x);
  50. public native double getDouble(Object o, long offset);
  51. public native void putDouble(Object o, long offset, double x);
  52. /**
  53. * 从特定位置获取一个对象
  54. */
  55. public native Object getObject(Object o, long offset)
  56. /**
  57. * 除非o==null或与参数x字段类型匹配,否则结果将是不确定的。
  58. * If the reference o is non-null,
  59. * car marks or other store barriers for that object (if the VM requires them) are updated.
  60. */
  61. public native void putObject(Object o, long offset, Object x);
  62. // 下面这些方法处理在C堆中的值
  63. /**
  64. * 从给定的内存地址中获取一个值。
  65. * 如果地址为零,或未指向从allocateMemory获取的块,则结果不确定。
  66. */
  67. public native byte getByte(long address);
  68. /**
  69. * 将值存储到给定的内存地址中。
  70. * 如果地址为零,或未指向从allocateMemory获取的块,则结果不确定。
  71. */
  72. public native void putByte(long address, byte x);
  73. public native short getShort(long address);
  74. public native void putShort(long address, short x);
  75. public native char getChar(long address);
  76. public native void putChar(long address, char x);
  77. public native int getInt(long address);
  78. public native void putInt(long address, int x);
  79. public native long getLong(long address);
  80. public native void putLong(long address, long x);
  81. public native float getFloat(long address);
  82. public native void putFloat(long address, float x);
  83. public native double getDouble(long address);
  84. public native void putDouble(long address, double x);
  85. /**
  86. * 从给定的内存地址中获取本地指针。如果地址为0,或未指向从 allocateMemory 获取的内存块,将导致结果不确定。
  87. */
  88. public native long getAddress(long address);
  89. /**
  90. * 存储一个本地指针到目标内存地址。如果地址为0,或未指向从 allocateMemory 获取的内存块,将导致结果不确定。
  91. * 实际写入的字节数是由 addressSize() 决定的。
  92. */
  93. public native void putAddress(long address, long x);
  94. // 包装C语言中的malloc、realloc、free函数
  95. /**
  96. * 分配给定大小的新本地内存块(以字节为单位)。
  97. * 存储器的内容未初始化,所以当使用此函数进行内存分配,需要对该内存块进行初始化设置。
  98. * 与freeMemory() 成对出现,否则只管分配不管释放最终会导致堆外内存用尽,程序报OOM异常。
  99. * 也可以通过 reallocateMemory(cap) 对已分配的内存块增大或缩小为 cap 大小。
  100. */
  101. public native long allocateMemory(long bytes);
  102. /**
  103. * 调整本地内存块的大小。当超过旧块大小的新块内容未初始化,通常是垃圾数据。
  104. * 结果指针对对齐所有值类型。
  105. * 如果参数 address == null,在这种情况下还会继续执行内存分配
  106. */
  107. public native long allocateMemory(long bytes);
  108. /**
  109. * 将给定内存块中的所有字节设置为一个固定值(通常为0)。
  110. * 这个函数通常用来做初始化用的。
  111. * 此方法通过两个参数确定块的基地址。因此,实际上提供了一个「双寄存器模式」。像 getInt(Object, long) 中所讨论的那样。
  112. * 当参数o==null时,偏移量offset表示的是本地内存的绝对地址。
  113. * 存储以连贯的(原子的)单位表示,其大小由地址和长度参数确定。
  114. * 如果有效地址和长度可以被8整除,则当前内存块表示「long」类型数据。
  115. * 如果有效地址和长度可以被4整除,则当前内存块表示「int」类型数据。
  116. * 如果有效地址和长度可以被2整除,则当前内存场合表示「short」类型数据。
  117. */
  118. public native void setMemory(Object o, long offset, long bytes, byte value);
  119. public void setMemory(long address, long bytes, byte value) {
  120. setMemory(null, address, bytes, value);
  121. }
  122. /**
  123. * 将给定内存块中的所有字节设置为另一个块的副本。
  124. * 此方法通过两个参数确定每个内存块的基地址,因此,实际上提供了一个「双寄存器模式」。和 getInt(Object, long) 中所讨论的那样。
  125. * 存储以连贯的(原子的)单位表示,其大小由地址和长度参数确定。
  126. * 如果有效地址和长度可以被8整除,则当前内存块表示「long」类型数据。
  127. * 如果有效地址和长度可以被4整除,则当前内存块表示「int」类型数据。
  128. * 如果有效地址和长度可以被2整除,则当前内存场合表示「short」类型数据。
  129. * @param srcBase 源对象
  130. * @param srcOffset 源对象的偏移量
  131. * @param destBase 目标对象
  132. * @param destOffset 目标对象的偏移量
  133. * @param bytes 拷贝长度
  134. */
  135. public native void copyMemory(Object srcBase, long srcOffset,
  136. Object destBase, long destOffset,
  137. long bytes);
  138. public void copyMemory(long srcAddress, long destAddress, long bytes) {
  139. copyMemory(null, srcAddress, null, destAddress, bytes);
  140. }
  141. /**
  142. * 将所有元素从一个内存复制到另一个内存块。
  143. *「unconditionally」 byte swapping the elements on the fly.
  144. */
  145. private native void copySwapMemory0(Object srcBase, long srcOffset,
  146. Object destBase, long destOffset,
  147. long bytes, long elemSize);
  148. /**
  149. * 释放由allocatemory、reallocatemory所分配的内存块。
  150. */
  151. public native void freeMemory(long address);
  152. // 随机查询
  153. // 这个常量不同于 staticFieldOffset, objectFieldOffset 或 arrayBaseOffset 返回的所有结果
  154. public static final int INVALID_FIELD_OFFSET = -1;
  155. /**
  156. * 获取给定字段在其类的存储分配中的位置。不要期望对这个偏移量执行任何类型的算术运算。
  157. * 它只是一个传递给不安全堆内存访问器的cookie。
  158. * 任何给定的字段将始终具有相同的偏移量和基数,同一类中任何两个不同的字段都不会具有相同的偏移量和基数。
  159. */
  160. public native long staticFieldOffset(Field f);
  161. /**
  162. * 和 staticFieldBase 一起获取静态字段的位置。
  163. */
  164. public native long objectFieldOffset(Field f);
  165. public native Object staticFieldBase(Field f);
  166. /**
  167. * 检测给定的类是否需要初始化。这通常需要与获取类的静态字段基一起使用。
  168. * @return false only if a call to {@code ensureClassInitialized} would have no effect
  169. */
  170. public native boolean shouldBeInitialized(Class<?> c);
  171. /**
  172. * 确保给定的类已经初始化。这通常需要与获取类的静态字段基一起使用。
  173. */
  174. public native void ensureClassInitialized(Class<?> c);
  175. /**
  176. * 获取给定数组类型的存储分配中用于寻址元素的缩放比例因子。
  177. * 通常"narrow"类型的数组不能使用比如 getByte() 获取
  178. */
  179. public native int arrayBaseOffset(Class<?> arrayClass);
  180. public static final int ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe.arrayBaseOffset(boolean[].class);
  181. public static final int ARRAY_BYTE_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
  182. public static final int ARRAY_SHORT_BASE_OFFSET = theUnsafe.arrayBaseOffset(short[].class);
  183. public static final int ARRAY_CHAR_BASE_OFFSET = theUnsafe.arrayBaseOffset(char[].class);
  184. public static final int ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset(int[].class);
  185. public static final int ARRAY_LONG_BASE_OFFSET = theUnsafe.arrayBaseOffset(long[].class);
  186. public static final int ARRAY_FLOAT_BASE_OFFSET = theUnsafe.arrayBaseOffset(float[].class);
  187. public static final int ARRAY_DOUBLE_BASE_OFFSET = theUnsafe.arrayBaseOffset(double[].class);
  188. public static final int ARRAY_OBJECT_BASE_OFFSET = = theUnsafe.arrayBaseOffset(Object[].class);
  189. /**
  190. * 获取给定数组类的存储分配中用于寻址元素的比例因子
  191. */
  192. public native int arrayIndexScale(Class<?> arrayClass);
  193. public static final int ARRAY_BOOLEAN_INDEX_SCALE = theUnsafe.arrayIndexScale(boolean[].class);
  194. public static final int ARRAY_BYTE_INDEX_SCALE = theUnsafe.arrayIndexScale(byte[].class);
  195. public static final int ARRAY_SHORT_INDEX_SCALE = theUnsafe.arrayIndexScale(short[].class);
  196. public static final int ARRAY_CHAR_INDEX_SCALE = theUnsafe.arrayIndexScale(char[].class);
  197. public static final int ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale(int[].class);
  198. public static final int ARRAY_LONG_INDEX_SCALE = theUnsafe.arrayIndexScale(long[].class);
  199. public static final int ARRAY_FLOAT_INDEX_SCALE = theUnsafe.arrayIndexScale(float[].class);
  200. public static final int ARRAY_DOUBLE_INDEX_SCALE = theUnsafe.arrayIndexScale(double[].class);
  201. public static final int ARRAY_OBJECT_INDEX_SCALE = theUnsafe.arrayIndexScale(Object[].class);
  202. /**
  203. *
  204. *
  205. *
  206. *
  207. */
  208. /**
  209. * 返回通过putAddress()存储的本地指针的大小(以字节为单位),
  210. * 这个值可能是4或8。
  211. * 注意在其他基本类型的大小完全由它们的信息内存所决定的
  212. */
  213. public native int addressSize();
  214. public static final int ADDRESS_SIZE = theUnsafe.addressSize();
  215. /**
  216. * 本地内存页的大小
  217. */
  218. public native int pageSize();
  219. // random trusted operations from JNI:
  220. /**
  221. * 定义一个类,该类是完全可信的,不需要进行安全检查
  222. */
  223. public native Class<?> defineClass(String name, byte[] b, int off, int len,
  224. ClassLoader loader,
  225. ProtectionDomain protectionDomain);
  226. /**
  227. * 定义一个匿名类,该类不会被类加载器或系统字典所知道。
  228. */
  229. public native Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches);
  230. /**
  231. * 实例化对象,但不需要经过任务构造器。
  232. * 如果该类还没有被初始化,则初始化该类
  233. */
  234. public native Object allocateInstance(Class<?> cls)
  235. throws InstantiationException;
  236. // 与锁相关
  237. @Deprecated
  238. public native void monitorEnter(Object o);
  239. @Deprecated
  240. public native void monitorExit(Object o);
  241. @Deprecated
  242. public native boolean tryMonitorEnter(Object o);
  243. public native void throwException(Throwable ee);
  244. /**
  245. * 「CAS」如果与期望值相等,则将对应属性更新为目标值
  246. * @param o 目标对象
  247. * @param offset 偏移量
  248. * @param expected 期望值
  249. * @param x 目标值
  250. * @return
  251. */
  252. public final native boolean compareAndSwapObject(Object o, long offset,
  253. Object expected,
  254. Object x);
  255. /**
  256. * 「CAS」如果与期望值相等,则将对应属性更新为目标值
  257. * @param o 目标对象
  258. * @param offset 偏移量
  259. * @param expected 期望值
  260. * @param x 目标值
  261. * @return
  262. */
  263. public final native boolean compareAndSwapInt(Object o, long offset,
  264. int expected,
  265. int x);
  266. /**
  267. * 「CAS」如果与期望值相等,则将对应属性更新为目标值
  268. * @param o 目标对象
  269. * @param offset 偏移量
  270. * @param expected 期望值
  271. * @param x 目标值
  272. * @return
  273. */
  274. public final native boolean compareAndSwapLong(Object o, long offset,
  275. long expected,
  276. long x);
  277. /**
  278. * 使用「volatile load」语义从给定的Java变量中获取引用值
  279. * 否则与getObject(Object, long)相同
  280. */
  281. public native Object getObjectVolatile(Object o, long offset);
  282. /**
  283. * 使用「volatile store」语义设置数据
  284. * 否则与 putObject(Object, long, Object)相同
  285. */
  286. public native void putObjectVolatile(Object o, long offset, Object x);
  287. public native int getIntVolatile(Object o, long offset);
  288. public native void putIntVolatile(Object o, long offset, int x);
  289. public native boolean getBooleanVolatile(Object o, long offset);
  290. public native void putBooleanVolatile(Object o, long offset, boolean x);
  291. public native byte getByteVolatile(Object o, long offset);
  292. public native void putByteVolatile(Object o, long offset, byte x);
  293. public native short getShortVolatile(Object o, long offset);
  294. public native void putShortVolatile(Object o, long offset, short x);
  295. public native char getCharVolatile(Object o, long offset);
  296. public native void putCharVolatile(Object o, long offset, char x);
  297. public native long getLongVolatile(ObjectputOrderedObject
  298. o, long offset);
  299. public native void putLongVolatile(Object o, long offset, long x);
  300. public native float getFloatVolatile(Object o, long offset);putOrderedObject
  301. public native void putFloatVolatile(Object o, long offset, float x);
  302. public native double getDoubleVolatile(Object o, long offset);
  303. public native void putDoubleVolatile(Object o, long offset, double x);
  304. /**
  305. * 不保证存储值对其他线程立即可见,属于 putObjectVolatile(Object, long, Object) 版本。
  306. * 在被volaile修饰的字段(或数组单元格,否则只能傅volatile访问)情况下才有用
  307. */
  308. public native void putOrderedObject(Object o, long offset, Object x);
  309. /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
  310. public native void putOrderedInt(Object o, long offset, int x);
  311. /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
  312. public native void putOrderedLong(Object o, long offset, long x);
  313. /**
  314. * 解除 对park上阻塞的 线程阻塞(Unblock the given thread blocked on park)
  315. * 如果线程没有阻塞,则后续的调用也不阻塞。
  316. * 注意: 这个操作「不安全」,仅仅是因为调用都必须以某种方式确保线程没有被销毁。
  317. * 通常不需要特别的东西来确保这一点,但当通过「native」方法调用时,这几乎不是自动的。
  318. */
  319. public native void unpark(Object thread);
  320. /**
  321. * 阻塞当前线程,直到
  322. * ① a balancing unpark occurs
  323. * ② a balancing unpark has already occurred
  324. * ③ 线程中断
  325. * ④ isAbsolute=false&time>0,则时间单位为纳秒,经过time纳秒后返回。
  326. * ⑤ isAbsolute=true&time>0,则时间单位为毫秒。经过time毫秒后返回。
  327. * ⑥ 未知原因错误直接返回
  328. * @param isAbsolute 是否为绝对时间
  329. * @param time 等待时间值
  330. */
  331. public native void park(boolean isAbsolute, long time);
  332. /**
  333. * 获取分配给可用处理器的系统运行队列中在不同时间段的平均负载。
  334. */
  335. public native int getLoadAverage(double[] loadavg, int nelems);
  336. // 非native的 CAS 实现
  337. /**
  338. * 「CAS」原子地将给定值添加到给定对象o的偏移量offset处(字段或数组元素)
  339. * @param o 目标对象
  340. * @param offset 字段或元素偏移量
  341. * @param delta 被加数
  342. * @return 旧值
  343. * @since 1.8
  344. */
  345. public final int getAndAddInt(Object o, long offset, int delta) {
  346. int v;
  347. do {
  348. // #1 获取旧值
  349. v = getIntVolatile(o, offset);
  350. // #2 通过「CAS」对于旧值是否可以更新,如果不可以,继续循环
  351. } while (!compareAndSwapInt(o, offset, v, v + delta));
  352. return v;
  353. }
  354. public final long getAndAddLong(Object o, long offset, long delta) {
  355. long v;
  356. do {
  357. v = getLongVolatile(o, offset);
  358. } while (!compareAndSwapLong(o, offset, v, v + delta));
  359. return v;
  360. }
  361. public final int getAndSetInt(Object o, long offset, int newValue) {
  362. int v;
  363. do {
  364. v = getIntVolatile(o, offset);
  365. } while (!compareAndSwapInt(o, offset, v, newValue));
  366. return v;
  367. }
  368. public final long getAndSetLong(Object o, long offset, long newValue) {
  369. long v;
  370. do {
  371. v = getLongVolatile(o, offset);
  372. } while (!compareAndSwapLong(o, offset, v, newValue));
  373. return v;
  374. }
  375. public final Object getAndSetObject(Object o, long offset, Object newValue) {
  376. Object v;
  377. do {
  378. v = getObjectVolatile(o, offset);
  379. } while (!compareAndSwapObject(o, offset, v, newValue));
  380. return v;
  381. }
  382. /**
  383. * 「store」将处理器缓存的数据刷新到内存中。
  384. * 「load」将内存存储的数据拷贝到处理器的缓存中。
  385. * 「load_load_barriers」确保load1的数据装载先于load2及其后所有装载指令的操作。
  386. * 「store_store_barriers」确保store1立刻刷新数据到内存(使其对其他处理器可见)的操作等于store2及其后所有存储指令的操作。
  387. * 「load_store_barriers」确保load1的数据装载等于store2及其后所有的存储指令刷新数据到内存的操作。
  388. * 「store_load_barriers」该屏障确保store1立刻刷新数据到内存的操作先于load2及其后所有装载指令的操作。
  389. * 它会使该屏障之前的所有内存访问指令(存储指令和访问指令)完成之后,才执行该屏障之后的内存访问指令。
  390. * 这一道内存屏障也称「全能屏障」
  391. */
  392. // Ensures lack of reordering of loads before the fence with loads or stores after the fence.
  393. public native void loadFence();
  394. /**
  395. * Ensures lack of reordering of stores before the fence
  396. * with loads or stores after the fence.
  397. * @since 1.8
  398. */
  399. public native void storeFence();
  400. /**
  401. * Ensures lack of reordering of loads or stores before the fence
  402. * with loads or stores after the fence.
  403. * @since 1.8
  404. */
  405. public native void fullFence();
  406. /**
  407. * Throws IllegalAccessError; for use by the VM.
  408. * @since 1.8
  409. */
  410. private static void throwIllegalAccessError() {
  411. throw new IllegalAccessError();
  412. }
  413. /**
  414. * 「big-endian」 本机字节顺序为「大端」,返回true
  415. * 「little-endian」 本机字节顺序为「小端」,返回false
  416. */
  417. public final boolean isBigEndian() { return BE; }
  418. /**
  419. * @return Returns true if this platform is capable of performing
  420. * accesses at addresses which are not aligned for the type of the
  421. * primitive type being accessed, false ocompareAndSwapObject
  422. therwise.
  423. */
  424. public final boolean unalignedAccess() { return unalignedAccess; }
  425. // JVM interface methods
  426. private native boolean unalignedAccess0();
  427. private native boolean isBigEndian0();
  428. // BE is true iff the native endianness of this platform is big.
  429. private static final boolean BE = theUnsafe.isBigEndian0();
  430. // unalignedAccess is true iff this platform can perform unaligned accesses.
  431. private static final boolean unalignedAccess = theUnsafe.unalignedAccess0();

putOrderedObject

/**
 * 向目标对象x偏移量为offset处写入对象o的引用,
 * 内存立即可见(volatile 保证)
 */
public native void putObjectVolatile(Object o, long offset, Object x);

/**
 * 向目标对象o偏移量为offset处写入对象x的引用,
 * 有序、延迟可见,即不能保证其他线程立即看到,性能比putObjectVolatile要高
 * 这个方法能使用store-store屏障,性能损耗较小,而volatile使用store-load屏障,性能损耗高。
 */
public native void putOrderedObject(Object o, long offset, Object x);

首先将 volatile 变量转为普通变量提升性能,因为在 put 中需要读取到最新的数据,因此接下来调用 UNSAFE.getObjectVolatile 获取到最新的头结点,但是通过调用 UNSAFE.putOrderedObject 让变量写入主存的时间延迟到 put 方法的结尾,一来缩小临界区提升性能,而来也能保证其他线程读取到的是完整数据。

Unsafe 底层原理

JVM 源码位于 unsafe.cpp 上:

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");
  oop p = JNIHandles::resolve(obj);
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

从源码可见,它是通过 Atomic::cmpxchg 实现比较和替换操作。参数 x 是目标值,参数 e 是旧值,addr 为目标地址。
而更底层 Linux 操作系统实现如下:

inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
  int mp = os::is_MP();
  __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
                    : "=a" (exchange_value)
                    : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
                    : "cc", "memory");
  return exchange_value;
}

引用

  1. Java魔法类:Unsafe应用解析