下面是Unsafe的主要功能:
* 普通讀寫:讀寫一個Object的field;直接從內存地址讀寫
* volatile讀寫:volatile讀寫Object的field,可以保證可見性和有序性
* 有序寫:有序寫Object的field,保證有序性不保證可見性
* 直接內存操作:申請內存;重新申請內存;釋放內存;內存復制
* CAS相關:提供int,long,和Object的CAS操作
* 偏移量相關:獲取對象屬性和靜態屬性的偏移量;獲取數組的arrayBaseOffset和arrayIndexScale
* 線程調度:掛起線程,喚醒線程,monitorEnter,monitorExit
* 類加載:定義類,創建對象,定義匿名內部類,確保一個類被加載,判斷是否加載一個類
* 內存屏障:讀屏障,寫屏障,讀寫屏障
* [1 獲取Unsafe實例](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#1_Unsafe_14)
* [2 普通讀寫](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#2__25)
* [3 volatile讀寫](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#3_volatile_96)
* [4 有序寫](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#4__103)
* [5 直接內存操作](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#5__109)
* [6 compareAndSwap相關](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#6_compareAndSwap_118)
* [7 偏移量相關](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#7__242)
* [8 線程調度](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#8__251)
* [9 類加載](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#9__262)
* [10 內存屏障](http://www.hmoore.net/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#10__276)
## 1 獲取Unsafe實例
通過反射獲取Unsafe實例:
~~~
public static Unsafe getUnsafe() throws IllegalAccessException {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
return unsafe;
}
~~~
## 2 普通讀寫
~~~
// 讀寫一個Object屬性的相關方法
public native int getInt(Object o, long l);
public native void putInt(Object o, long l, int i);
// 讀寫內存地址屬性的相關方法
public native int getInt(long l);
public native void putInt(long l, int i);
~~~
下面是測試用例:
~~~
package sun.misc;
import java.lang.reflect.Field;
/**
*
* @author zhaoxuyang
*/
public class UnsafeTest {
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
Model m = new Model(1, "zhangsan", 22);
sun.misc.Unsafe unsafe = getUnsafe();
System.out.println(unsafe.toString());
Class<?> c = Model.class;
long idOffset = unsafe.objectFieldOffset(c.getDeclaredField("id"));
long nameOffset = unsafe.objectFieldOffset(c.getDeclaredField("name"));
long ageOffset = unsafe.objectFieldOffset(c.getDeclaredField("age"));
System.out.println("idOffset: " + idOffset);
System.out.println("nameOffset: " + nameOffset);
System.out.println("ageOffset: " + ageOffset);
// 讀寫一個Object屬性的相關方法
int getIntId = unsafe.getInt(m, idOffset);
int getIntName = unsafe.getInt(m, nameOffset);
int getIntAge = unsafe.getInt(m, ageOffset);
System.out.println(getIntId);
System.out.println(getIntName);
System.out.println(getIntAge);
unsafe.putInt(m, ageOffset, getIntAge + 1);
System.out.println(m.age);
}
public static Unsafe getUnsafe() throws IllegalAccessException {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
return unsafe;
}
private static class Model {
long id;
String name;
int age;
Model(long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
}
~~~
## 3 volatile讀寫
~~~
// 普通的讀寫無法保證可見性和有序性,而volatile讀寫就可以保證可見性和有序性。
public native int getIntVolatile(Object o, long l);
public native void putIntVolatile(Object o, long l, int i);
~~~
## 4 有序寫
~~~
// 有序寫入只保證寫入的有序性,不保證可見性,即一個線程的寫入不保證其他線程立馬可見,但是效率比volatile高。
public native void putOrderedInt(Object o, long l, int i);
~~~
## 5 直接內存操作
~~~
public native long allocateMemory(long l); // 分配內存
public native long reallocateMemory(long l, long l1); // 重新分配內存
public native void setMemory(Object o, long l, long l1, byte b); // 內存初始化
public native void copyMemory(Object o, long l, Object o1, long l1, long l2); // 內存復制
public native void freeMemory(long l); // 清除內存
~~~
## 6 compareAndSwap相關
Unsafe中提供了int,long和Object的CAS操作:
~~~
public final native boolean compareAndSwapObject(Object o, long l, Object o1, Object o2);
public final native boolean compareAndSwapInt(Object o, long l, int i, int i1);
public final native boolean compareAndSwapLong(Object o, long l, long l1, long l2);
~~~
CAS示例如下:
~~~
package sun.misc;
import java.lang.reflect.Field;
/**
*
* @author zhaoxuyang
*/
public class CasDemo{
private volatile int value;
private static final long valueOffset;
private final static Unsafe unsafe;
static {
try {
unsafe = getUnsafe();
valueOffset = unsafe.objectFieldOffset(CasDemo.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private static Unsafe getUnsafe() throws IllegalAccessException {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
return unsafe;
}
public final boolean cas(int expect, int update){
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final int getAndIncr(){
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndDecr(){
return unsafe.getAndAddInt(this, valueOffset, -1);
}
public final int getValue(){
return value;
}
}
~~~
下面的例子將實現兩個線程交替打印奇偶數:
~~~
package sun.misc;
/**
*
* @author zhaoxuyang
*/
public class CasDemoTest {
public static void main(String[] args) throws InterruptedException {
CasDemo casDemo = new CasDemo();
System.out.println(casDemo.getValue());
Thread t1 = new Thread(() -> {
while(true){
int value = casDemo.getValue();
if(value > 10){
break;
}
if(value % 2 == 1){
System.out.println("線程1 " + value);
casDemo.cas(value, value + 1);
}
}
});
Thread t2 = new Thread(() -> {
while(true){
int value = casDemo.getValue();
if(value > 10){
break;
}
if(value % 2 == 0){
System.out.println("線程2 " + value);
casDemo.cas(value, value + 1);
}
}
});
t1.start();
t2.start();
Thread.sleep(200);
System.out.println(casDemo.getValue());
}
}
~~~
輸出如下:
~~~
run:
0
線程2 0
線程1 1
線程2 2
線程1 3
線程2 4
線程1 5
線程2 6
線程1 7
線程2 8
線程1 9
線程2 10
11
~~~
## 7 偏移量相關
~~~
public native long staticFieldOffset(Field field); // 獲取靜態屬性Field在對象中的偏移量
public native long objectFieldOffset(Field field); // 非靜態屬性Field在對象實例中的偏移量
public native Object staticFieldBase(Field field); // 返回Field所在的對象
public native int arrayBaseOffset(Class<?> type); // 返回數組中第一個元素實際地址相對數組地址的偏移量
public native int arrayIndexScale(Class<?> type); //計算數組中第一個元素所占用的內存空間
~~~
## 8 線程調度
~~~
public native void park(boolean bln, long l); // 掛起線程
public native void unpark(Object o); // 喚醒線程
// 用于加鎖,synchronized便是通過以下指令實現
@Deprecated public native void monitorEnter(Object o);
@Deprecated public native void monitorExit(Object o);
@Deprecated public native boolean tryMonitorEnter(Object o);
~~~
## 9 類加載
~~~
// 定義一個類,用于動態地創建類
public native Class<?> defineClass(String string, byte[] bytes, int i, int i1, ClassLoader cl, ProtectionDomain pd);
// 用于動態地創建一個匿名內部類
public native Class<?> defineAnonymousClass(Class<?> type, byte[] bytes, Object[] os);
// 用于創建一個類的實例,但是不會調用這個實例的構造方法,如果這個類還未被初始化,則初始化這個類。
public native Object allocateInstance(Class<?> type) throws InstantiationException;
// 用于判斷是否需要初始化一個類
public native boolean shouldBeInitialized(Class<?> type);
// 用于保證已經初始化過一個類
public native void ensureClassInitialized(Class<?> type);
~~~
## 10 內存屏障
~~~
public native void loadFence(); // 保證在這個屏障之前的所有【讀】操作都已經完成
public native void storeFence(); // 【寫】
public native void fullFence(); // 【讀寫】
~~~
- 空白目錄
- 精簡版Spring的實現
- 0 前言
- 1 注冊和獲取bean
- 2 抽象工廠實例化bean
- 3 注入bean屬性
- 4 通過XML配置beanFactory
- 5 將bean注入到bean
- 6 加入應用程序上下文
- 7 JDK動態代理實現的方法攔截器
- 8 加入切入點和aspectj
- 9 自動創建AOP代理
- Redis原理
- 1 Redis簡介與構建
- 1.1 什么是Redis
- 1.2 構建Redis
- 1.3 源碼結構
- 2 Redis數據結構與對象
- 2.1 簡單動態字符串
- 2.1.1 sds的結構
- 2.1.2 sds與C字符串的區別
- 2.1.3 sds主要操作的API
- 2.2 雙向鏈表
- 2.2.1 adlist的結構
- 2.2.2 adlist和listNode的API
- 2.3 字典
- 2.3.1 字典的結構
- 2.3.2 哈希算法
- 2.3.3 解決鍵沖突
- 2.3.4 rehash
- 2.3.5 字典的API
- 2.4 跳躍表
- 2.4.1 跳躍表的結構
- 2.4.2 跳躍表的API
- 2.5 整數集合
- 2.5.1 整數集合的結構
- 2.5.2 整數集合的API
- 2.6 壓縮列表
- 2.6.1 壓縮列表的結構
- 2.6.2 壓縮列表結點的結構
- 2.6.3 連鎖更新
- 2.6.4 壓縮列表API
- 2.7 對象
- 2.7.1 類型
- 2.7.2 編碼和底層實現
- 2.7.3 字符串對象
- 2.7.4 列表對象
- 2.7.5 哈希對象
- 2.7.6 集合對象
- 2.7.7 有序集合對象
- 2.7.8 類型檢查與命令多態
- 2.7.9 內存回收
- 2.7.10 對象共享
- 2.7.11 對象空轉時長
- 3 單機數據庫的實現
- 3.1 數據庫
- 3.1.1 服務端中的數據庫
- 3.1.2 切換數據庫
- 3.1.3 數據庫鍵空間
- 3.1.4 過期鍵的處理
- 3.1.5 數據庫通知
- 3.2 RDB持久化
- 操作系統
- 2021-01-08 Linux I/O 操作
- 2021-03-01 Linux 進程控制
- 2021-03-01 Linux 進程通信
- 2021-06-11 Linux 性能優化
- 2021-06-18 性能指標
- 2022-05-05 Android 系統源碼閱讀筆記
- Java基礎
- 2020-07-18 Java 前端編譯與優化
- 2020-07-28 Java 虛擬機類加載機制
- 2020-09-11 Java 語法規則
- 2020-09-28 Java 虛擬機字節碼執行引擎
- 2020-11-09 class 文件結構
- 2020-12-08 Java 內存模型
- 2021-09-06 Java 并發包
- 代碼性能
- 2020-12-03 Java 字符串代碼性能
- 2021-01-02 ASM 運行時增強技術
- 理解Unsafe
- Java 8
- 1 行為參數化
- 1.1 行為參數化的實現原理
- 1.2 Java 8中的行為參數化
- 1.3 行為參數化 - 排序
- 1.4 行為參數化 - 線程
- 1.5 泛型實現的行為參數化
- 1.6 小結
- 2 Lambda表達式
- 2.1 Lambda表達式的組成
- 2.2 函數式接口
- 2.2.1 Predicate
- 2.2.2 Consumer
- 2.2.3 Function
- 2.2.4 函數式接口列表
- 2.3 方法引用
- 2.3.1 方法引用的類別
- 2.3.2 構造函數引用
- 2.4 復合方法
- 2.4.1 Comparator復合
- 2.4.2 Predicate復合
- 2.4.3 Function復合
- 3 流處理
- 3.1 流簡介
- 3.1.1 流的定義
- 3.1.2 流的特點
- 3.2 流操作
- 3.2.1 中間操作
- 3.2.2 終端操作
- 3.3.3 構建流
- 3.3 流API
- 3.3.1 flatMap的用法
- 3.3.2 reduce的用法
- 3.4 collect操作
- 3.4.1 collect示例
- 3.4.2 Collector接口