本文主要是介绍共享模型之无锁——Unsafe,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 概述
- Unsafe CAS 操作
名字虽然叫Unsafe,但并不是线程不安全,而是因为他会操作内存,操作线程,不建议开发人员使用。
概述
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;}
}
Unsafe CAS 操作
我们使用Unsafe的cas操作,来线程安全的对Teacher对象的成员变量进行修改。
因为更底层,所有要更麻烦。
public class TestUnsafe {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); // getDeclaredField反射获得私有成员变量theUnsafe.setAccessible(true); // 允许访问私有成员变量Unsafe unsafe = (Unsafe) theUnsafe.get(null); //theUnsafe成员变量是静态的,静态成员变量从属于类,不从属于对象,所以直接传null值System.out.println(unsafe);// 1. 获取域的偏移地址long idOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("id"));long nameOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("name"));Teacher t = new Teacher();// 2. 执行 cas 操作unsafe.compareAndSwapInt(t, idOffset, 0, 1);unsafe.compareAndSwapObject(t, nameOffset, null, "张三");// 3. 验证System.out.println(t);}
}
@Data
class Teacher {volatile int id;volatile String name;
}
输出
sun.misc.Unsafe@4d7e1886
Teacher(id=1, name=张三)
使用自定义的 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,如果期间旧值被别的线程改了,返回 falseif (unsafe.compareAndSwapInt(this, DATA_OFFSET, oldValue, oldValue - amount)) {return;}}}public int getData() {return data;}
}
Account 实现
Account.demo(new Account() {AtomicData atomicData = new AtomicData(10000);@Overridepublic Integer getBalance() {return atomicData.getData();}@Overridepublic void withdraw(Integer amount) {atomicData.decrease(amount);}
});
这篇关于共享模型之无锁——Unsafe的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!