Skip to Content

JavaUnsafe类

Unsafe 对象提供了非常底层的,操作内存、线程的方法,Unsafe 对象不能直接调用,只能通过反射获得。

public class UnsafeAccessor { static Unsafe unsafe; static { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); unsafe = (Unsafe) theUnsafe.get(null); } catch (NoSuchFieldException | IllegalAccessException e) { throw new Error(e); } } static Unsafe getUnsafe() { return unsafe; } }

CAS操作

Unsafe unsafe = UnsafeAccessor.getUnsafe(); Field id = Student.class.getDeclaredField("id"); Field name = Student.class.getDeclaredField("name"); // 获得成员变量的偏移量 long idOffset = UnsafeAccessor.unsafe.objectFieldOffset(id); long nameOffset = UnsafeAccessor.unsafe.objectFieldOffset(name); Student student = new Student(); // 使用 cas 方法替换成员变量的值 UnsafeAccessor.unsafe.compareAndSwapInt(student, idOffset, 0, 20); // 返回 true UnsafeAccessor.unsafe.compareAndSwapObject(student, nameOffset, null, "张三"); // 返回 true System.out.println(student);

使用自定义的 AtomicData 实现之前线程安全的原子整数 Account 实现:

class AtomicData { private volatile int data; static final Unsafe unsafe; static final long DATA_OFFSET; static { unsafe = UnsafeAccessor.getUnsafe(); try { // data 属性在 DataContainer 对象中的偏移量,用于 Unsafe 直接访问该属性 DATA_OFFSET = unsafe.objectFieldOffset(AtomicData.class.getDeclaredField("data")); } catch (NoSuchFieldException e) { throw new Error(e); } } public AtomicData(int data) { this.data = data; } public void decrease(int amount) { int oldValue; while(true) { // 获取共享变量旧值,可以在这一行加入断点,修改 data 调试来加深理解 oldValue = data; // cas 尝试修改 data 为 旧值 + amount,如果期间旧值被别的线程改了,返回 false if (unsafe.compareAndSwapInt(this, DATA_OFFSET, oldValue, oldValue - amount)) { return; } } } public int getData() { return data; } }
Last updated on