unsafe 的获取
unsafe 提供了非常底层,操作内存,线程的方法,unsafe 对象不能直接获取,只能通过反射获取
//自己获取会报错,因为校验了只能通过根加载器的类才能通过这个方法获取
Unsafe unsafe = Unsafe.getUnsafe();
通过反射获取
public class UnsafeAccessor {
private static Unsafe unsafe;
static {
try {
Field unsafeFile = Unsafe.class.getDeclaredField("theUnsafe");
unsafeFile.setAccessible(true);
//因为是静态属性
unsafe = (Unsafe) unsafeFile.get(null);
}catch (Exception e){}
}
public static Unsafe getUnsafe(){
return unsafe;
}
}
unsafe 的cas操作
public class UnsafeTest {
//
public static void main(String[] args) throws Exception{
Unsafe unsafe = UnsafeAccessor.getUnsafe();
//获取域的偏移地址
long i = unsafe.objectFieldOffset(Sut.class.getDeclaredField("i"));
long j = unsafe.objectFieldOffset(Sut.class.getDeclaredField("name"));
Sut sut = new Sut();
/**
* var1: 那个对象
* var2: 对象中的域的位置
* var3 : 需要比较的值
* var4 : 设置之后的值
*/
//如果sut对象中i的值为0,就设置为1,比较和设置是原子操纵
unsafe.compareAndSwapInt(sut,i,0,1);
unsafe.compareAndSwapObject(sut,j,null,"huge");
System.out.println(sut.name);
}
static class Sut{
volatile int i;
volatile String name;
}
}
unsafe 实现线程安全的累加器
public class AtomicData {
private volatile int data;
private final static Unsafe UNSAFE;
static long DATE_OFFSET;
static {
UNSAFE = UnsafeAccessor.getUnsafe();
try {
DATE_OFFSET = UNSAFE.objectFieldOffset(AtomicData.class.getDeclaredField("data"));
} catch (Exception e) {
e.printStackTrace();
}
}
public AtomicData(int data){
this.data = data;
}
public int getValue(){
return this.data;
}
public void incr(int data){
while (true){
int pre = this.data;
int next = pre + data;
if(UNSAFE.compareAndSwapInt(this,DATE_OFFSET,pre,next)){
break;
}
}
}
public static void main(String[] args) throws InterruptedException {
AtomicData atomicData = new AtomicData(0);
Thread t1 = new Thread(()->{
for (int i = 0;i < 5000;i++){
atomicData.incr(1);
}
});
Thread t2 = new Thread(()->{
for (int i = 0;i < 5000;i++){
atomicData.incr(1);
}
});
t1.start();
t2.start();
t1.join();
t2.join();
int value = atomicData.getValue();
System.out.println(value);
}
}