修改对象的字段
package org.example.concurrency.test;
import lombok.Data;
import sun.misc.Unsafe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* @author huskyui
*/
public class Test33 {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("sun.misc.Unsafe");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructors()[0];
declaredConstructor.setAccessible(true);
Unsafe unsafe = (Unsafe)declaredConstructor.newInstance(new Object[0]);
System.out.println(unsafe);
Student student = new Student();
Field id = Student.class.getDeclaredField("id");
Field name = Student.class.getDeclaredField("name");
long idOffset = unsafe.objectFieldOffset(id);
long nameOffset = unsafe.objectFieldOffset(name);
boolean b = unsafe.compareAndSwapInt(student, idOffset, 0, 1);
System.out.println(unsafe.compareAndSwapObject(student, nameOffset, null, "huskyui"));
System.out.println(b);
System.out.println(student);
}
}
@Data
class Student{
volatile int id;
volatile String name;
}
Unsafe需要通过反射反射获取对象。修改对象字段的时候,需要获得字段的offset值
实现一个原子类
package org.example.concurrency.test;
import sun.misc.Unsafe;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
/**
* @author huskyui
*/
public class MyAtomicInteger {
private volatile int data;
static Unsafe unsafe = null;
static long DATA_OFFSET = 0;
static {
try {
Class<?> aClass = Class.forName("sun.misc.Unsafe");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructors()[0];
declaredConstructor.setAccessible(true);
unsafe = (Unsafe) declaredConstructor.newInstance(new Object[0]);
System.out.println(unsafe);
DATA_OFFSET = unsafe.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("data"));
}catch (Exception e){
e.printStackTrace();
}
}
public MyAtomicInteger(int data) {
this.data = data;
}
public int get(){
return data;
}
public void decrease(int amount){
while (true) {
int prev = get();
int next = prev - amount;
if (unsafe.compareAndSwapInt(this, DATA_OFFSET, prev, next)){
break;
}
}
}
public static void main(String[] args) {
MyAtomicInteger myAtomicInteger = new MyAtomicInteger(10000);
long start = System.nanoTime();
List<Thread> ts = new ArrayList<>();
for (int i = 0;i<1000;i++){
ts.add(new Thread(()->{
myAtomicInteger.decrease(10);
}));
}
ts.forEach(Thread::start);
for (Thread t : ts) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long cost = System.nanoTime()-start;
System.out.println("cost" + (cost/1000/10000)+ " amount" + myAtomicInteger.get());
}
}