JDK的rt.jar包中的Unsafe類提供了硬體級別的原子性操作,Unsafe類中的方法都是native方法,它們使用JNI的方式訪問本地C++ 實現庫。下面我們來了解一下Unsafe提供的幾個主要的方法以及程式設計時如何使用Unsafe類做一些事情。
- long objectFieldOffset(Field field)方法:返回指定的變數在所屬類中的記憶體偏移地址,該偏移地址僅僅在該Unsafe函式中訪問指定欄位時使用。
- boolean compareAndSwapLong(Object obj, longoffset, long expect, long update)方法:比較物件obj中偏移量為offset的變數的值是否與expect相等,相等則使用update值更新,然後返回true,否則返回false。
- public native long getLongvolatile(Object obj, longoffset)方法:獲取物件obj中偏移量為offset的變數對應volatile語義的值。
- void putLongvolatile(Object obj, long offset, longvalue)方法:設定obj物件中offset偏移的型別為long的field的值為value,支援volatile語義。
public class UnsafeTest {
//獲得Unsafe的一個例項
static final Unsafe unsafe;
static final long stateOffset;
private volatile long state = 0;
static {
try {
// 使用反射獲取Unsafe的成員變數theUnsafe
Field field = Unsafe.class.getDeclaredField("theUnsafe");
// 設定為可存取
field.setAccessible(true);
// 獲取該變數的值
unsafe = (Unsafe) field.get(null);
// 獲取 UnsafeTest 類裡面的 state 變數, 在 UnsafeTest 物件裡面的記憶體偏移量地址並將其儲存到 stateOffset 變數中。
// getDeclaredFields():獲得某個類的所有宣告的欄位
stateOffset = unsafe.objectFieldOffset(UnsafeTest.class.getDeclaredField("state"));
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
throw new Error(e);
}
}
public static void main(String[] args){
UnsafeTest unsafeTest = new UnsafeTest();
// 如果 unsafeTest 物件中 記憶體偏移量為 stateOffset 的 state 變數的值為 0,則更新該值為 1
boolean b = unsafe.compareAndSwapLong(unsafeTest, stateOffset, 0, 1);
System.out.println(b);//true
System.out.println(unsafeTest.state);
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結