修改对象的字段
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);}}@Dataclass 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());}}
