java 中的Unsafe

這個類是用於執行低級別、不安全操作的方法集合。儘管這個類和所有的方法都是公開的(public),但是這個類的使用仍然受限,你無法在自己的java程序中直接使用該類,因爲只有授信的代碼才能獲得該類的實例。

從上面的描述,可以瞭解到該類是用來執行較低級別的操作的,比如獲取某個屬性在內存中的位置,不過一般人很少會有這樣的需求。在AtomicInteger的源碼中相關的代碼如下:

// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
上面這行代碼是獲取Unsafe實例的。一般情況下,我們是拿不到該類的實例的,當然jdk庫裏面是可以隨意使用的。

 static {
      try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
      } catch (Exception ex) { throw new Error(ex); }
    }
上面這幾行代碼,是用來獲取AtomicInteger實例中的value屬性在內存中的位置。這裏使用了Unsafe的objectFieldOffset方法。這個方法是一個本地方法, 該方法用來獲取一個給定的靜態屬性的位置。

public native long objectFieldOffset(Field f);
這裏有個疑問,爲什麼需要獲取屬性在內存中的位置?通過查看AtomicInteger源碼發現,在這樣幾個地方使用到了這個valueOffset值:
public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }
public final boolean compareAndSet(int expect, int update) {
	return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
public final boolean weakCompareAndSet(int expect, int update) {
	return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

查找資料後,發現lazySet方法大多用在併發的數據結構中,用於低級別的優化。compareAndSet這個方法多見於併發控制中,簡稱CAS(Compare And Swap),意思是如果valueOffset位置包含的值與expect值相同,則更新valueOffset位置的值爲update,並返回true,否則不更新,返回false。

這裏可以舉個例子來說明compareAndSet的作用,如支持併發的計數器,在進行計數的時候,首先讀取當前的值,假設值爲a,對當前值 + 1得到b,但是+1操作完以後,並不能直接修改原值爲b,因爲在進行+1操作的過程中,可能會有其它線程已經對原值進行了修改,所以在更新之前需要判斷原值是不是等於a,如果不等於a,說明有其它線程修改了,需要重新讀取原值進行操作,如果等於a,說明在+1的操作過程中,沒有其它線程來修改值,我們就可以放心的更新原值了。



Unsafe類中還包含有很多其它的方法,如果想使用其中的方法,可以參考這篇文章來獲取Unsafe的實例:http://javafans.info/java/corejava/15.html。



發佈了25 篇原創文章 · 獲贊 11 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章