下面是Unsafe的主要功能:
* 普通读写:读写一个Object的field;直接从内存地址读写
* volatile读写:volatile读写Object的field,可以保证可见性和有序性
* 有序写:有序写Object的field,保证有序性不保证可见性
* 直接内存操作:申请内存;重新申请内存;释放内存;内存复制
* CAS相关:提供int,long,和Object的CAS操作
* 偏移量相关:获取对象属性和静态属性的偏移量;获取数组的arrayBaseOffset和arrayIndexScale
* 线程调度:挂起线程,唤醒线程,monitorEnter,monitorExit
* 类加载:定义类,创建对象,定义匿名内部类,确保一个类被加载,判断是否加载一个类
* 内存屏障:读屏障,写屏障,读写屏障
* [1 获取Unsafe实例](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#1_Unsafe_14)
* [2 普通读写](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#2__25)
* [3 volatile读写](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#3_volatile_96)
* [4 有序写](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#4__103)
* [5 直接内存操作](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#5__109)
* [6 compareAndSwap相关](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#6_compareAndSwap_118)
* [7 偏移量相关](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#7__242)
* [8 线程调度](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#8__251)
* [9 类加载](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#9__262)
* [10 内存屏障](https://www.kancloud.cn/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接口