本文首發於一世流雲的專欄: https://segmentfault.com/blog...
在正式的開講 juc-atomic框架系列以前,有必要先來了解下Java中的Unsafe類。segmentfault
Unsafe類,來源於sun.misc
包。該類封裝了許多相似指針操做,能夠直接進行內存管理、操縱對象、阻塞/喚醒線程等操做。Java自己不直接支持指針的操做,因此這也是該類命名爲Unsafe的緣由之一。框架
J.U.C中的許多CAS方法,內部其實都是Unsafe類在操做。
好比AtomicBoolean
的compareAndSet
方法:atom
unsafe.compareAndSwapInt
方法是個native方法。(若是對象中的字段值與指望值相等,則將字段值修改成x,而後返回true;不然返回false):spa
入參的含義以下:線程
參數名稱 | 含義 |
---|---|
o | 須要修改的對象 |
offset | 須要修改的字段到對象頭的偏移量(經過偏移量,能夠快速定位修改的是哪一個字段) |
expected | 指望值 |
x | 要設置的值 |
Unsafe類中CAS方法都是native方法,須要經過CAS原子指令完成。在講AQS時,裏面有許多涉及CLH隊列的操做,其實就是經過Unsafe類完成的指針操做。3d
Unsafe是一個final類,不能被繼承,也沒有公共的構造器,只能經過工廠方法getUnsafe得到Unsafe的單例。指針
可是getUnsafe方法限制了調用該方法的類的類加載器必須爲Bootstrap ClassLoader。code
Java中的類加載器能夠大體劃分爲如下三類:對象
類加載器名稱 | 做用 |
---|---|
Bootstrap類加載器(Bootstrap ClassLoader) | 主要加載的是JVM自身須要的類,這個類加載使用C++語言實現的,是JVM自身的一部分,它負責將 【JDK的安裝目錄】/lib路徑下的核心類庫,如rt.jar |
擴展類加載器(Extension ClassLoader) | 該加載器負責加載【JDK的安裝目錄】jrelibext目錄中的類庫,開發者能夠直接使用該加載器 |
系統類加載器(Application ClassLoader) | 負責加載用戶類路徑(ClassPath)所指定的類,開發者能夠直接使用該類加載器,也是默認的類加載器 |
因此在用戶代碼中直接調用getUnsafe方法,會拋出異常。由於用戶自定義的類通常都是由系統類加載器加載的。blog
可是,是否就真的沒有辦法獲取到Unsafe實例了呢?固然不是,要獲取Unsafe對象的方法不少,這裏給出一種經過反射的方法:
Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe unsafe = (Unsafe) f.get(null);
可是,除非對Unsafe的實現很是清楚,不然應儘可能避免直接使用Unsafe來進行操做。