Java如何使用Unsafe类
发表于:2025-11-16 作者:千家信息网编辑
千家信息网最后更新 2025年11月16日,这篇文章将为大家详细讲解有关Java如何使用Unsafe类,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Unsafe 对象提供了非常底层的,操作内存、线程的方法,相
千家信息网最后更新 2025年11月16日Java如何使用Unsafe类
这篇文章将为大家详细讲解有关Java如何使用Unsafe类,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
Unsafe 对象提供了非常底层的,操作内存、线程的方法,相当于开了后门。
在atomic类中CAS实现、LockSupport中park unpark的底层都调用了UnSafe中的方法。
UnSafe并不是说线程不安全,而是说操作内存有可能会造成不安全问题。
当然对于开发人员来说
Unsafe 对象不能直接调用,只能通过反射获得
通过反射获得Unsafe对象
package com.dongguo.unsafe;import sun.misc.Unsafe;import java.lang.reflect.Field;/** * @author Dongguo * @date 2021/9/12 0012-21:32 * @description: */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; } public static void main(String[] args) { Unsafe unsafe = getUnsafe(); System.out.println(unsafe); }}运行结果
sun.misc.Unsafe@7ea987ac
使用Unsafe实现 CAS 操作
package com.dongguo.unsafe;import lombok.Data;import sun.misc.Unsafe;import java.lang.reflect.Field;/** * @author Dongguo * @date 2021/9/12 0012-21:32 * @description: */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; } public static void main(String[] args) throws NoSuchFieldException { Unsafe unsafe = getUnsafe(); System.out.println(unsafe); Field id = Student.class.getDeclaredField("id"); Field name = Student.class.getDeclaredField("name"); // 获得成员变量的偏移量 long idOffset = unsafe.objectFieldOffset(id); long nameOffset = unsafe.objectFieldOffset(name); Student student = new Student(); // 使用 cas 方法替换成员变量的值 unsafe.compareAndSwapInt(student, idOffset, 0, 20); // 返回 true 0为旧值 20为新值 unsafe.compareAndSwapObject(student, nameOffset, null, "张三"); // 返回 true 旧值为null,新值为张三 System.out.println(student); }}@Dataclass Student { volatile int id; volatile String name;}运行结果
sun.misc.Unsafe@7ea987ac
Student(id=20, name=张三)
直接使用Unsafe类实现之前AtomicIntegerFieldUpdater中线程安全的原子整数 BankAccount
在atomic中使用AtomicIntegerFieldUpdater实现money线程安全的原子整数
package com.dongguo.unsafe;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;/** * @author Dongguo * @date 2021/9/7 0007-14:41 * 以一种线程安全的方式操作非线程安全对象的某些字段。 * 需求: * 1000个人同时向一个账号转账一元钱,那么累计应该增加1000元, * 除了synchronized和CAS,还可以使用AtomicIntegerFieldUpdater来实现。 */class BankAccount { private String bankName = "ACBC"; public volatile int money = 0; AtomicIntegerFieldUpdater fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class, "money"); public void transferMoney(BankAccount bankAccount) { fieldUpdater.incrementAndGet(bankAccount); }}public class AtomicIntegerFieldUpdaterDemo { public static void main(String[] args) { BankAccount bankAccount = new BankAccount(); for (int i = 1; i <= 1000; i++) { new Thread(() -> { bankAccount.transferMoney(bankAccount); }, String.valueOf(i)).start(); } //暂停毫秒 try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(bankAccount.money); }} 改为使用UnSafe实现money线程安全的原子整数
package com.dongguo.unsafe;import sun.misc.Unsafe;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;/** * @author Dongguo * @date 2021/9/7 0007-14:41 */class BankAccount { private String bankName = "ACBC"; public volatile int money; static final Unsafe unsafe; static final long DATA_OFFSET; static { unsafe = UnsafeAccessor.getUnsafe(); try { // money 属性在 BankAccount 对象中的偏移量,用于 Unsafe 直接访问该属性 DATA_OFFSET = unsafe.objectFieldOffset(BankAccount.class.getDeclaredField("money")); } catch (NoSuchFieldException e) { throw new Error(e); } } public BankAccount(int money) { this.money = money; } public void transferMoney(int amount) { int oldValue; while (true) { // 获取共享变量旧值,可以在这一行加入断点,修改 data 调试来加深理解 oldValue = money; // cas 尝试修改 data 为 旧值 + amount,如果期间旧值被别的线程改了,返回 false if (unsafe.compareAndSwapInt(this, DATA_OFFSET, oldValue, oldValue + amount)) { return; } } }}public class AtomicIntegerFieldUpdaterDemo { public static void main(String[] args) { BankAccount bankAccount = new BankAccount(0); for (int i = 1; i <= 1000; i++) { new Thread(() -> { bankAccount.transferMoney(1); }, String.valueOf(i)).start(); } //暂停毫秒 try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(bankAccount.money); }}运行结果1000/暂停毫秒 try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(bankAccount.money); }}运行结果
1000
关于"Java如何使用Unsafe类"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
线程
安全
对象
结果
运行
原子
变量
整数
方法
篇文章
张三
内存
属性
底层
成员
更多
偏移
反射
不错
实用
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
徐州idc服务器
温州http服务器
SQL数据库创建连接服务器
虚拟技术与软件开发公司
考研网络安全的专业
聚聘互联网科技有限公司架构
互联网巨头与科技公司
河南交管12123服务器在哪里
杭州软件开发要求
天津电子软件开发公司国企
现代通信及网络技术
企业常用服务器
国家网络安全法律法有哪些规
服务器客户端软件开发
文成标准刀片服务器专业服务
方正网络技术有限公司
外国云服务器大全
后台服务器管理
服务器内存和普通
软件开发企业宣传册
辽宁语音网络技术分类创新服务
服务器如何获得大量资源
辽宁省网络安全题库及答案
一关机就连不上服务器了怎么办
密云区运营网络技术售后服务
minio使用服务器两个硬盘
如何选择当前操作的数据库
北京优万网络技术有限公司
邮件服务器实现
数据库英语名词