Unsafe类的使用

news2024/11/15 9:46:29

目录

    • 一、Unsafe是什么?
    • 二、Unsafe对象的获取
    • 三、CAS
      • 1、相关方法
      • 2、demo
    • 四、数组操作
    • 五、内存分配
    • 六、线程调度

参考于:https://blog.csdn.net/Wisimer/article/details/115220750

一、Unsafe是什么?

Unsafe是jdk提供的一个直接访问操作系统资源的工具类(底层c++实现),它可以直接分配内存,内存复制,copy,提供cpu级别的CAS乐观锁等操作

Unsafe位于sun.misc包下,jdk中的并发编程包juc(java.util.concurrent)基本全部靠Unsafe实现,由此可见其重要性。

二、Unsafe对象的获取

查看源码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结论:

  • Unsafe是饿汉式的单例模式
  • 只允许被引导类加载器(BootstrapClassLoader)加载的类使用,查看源码可以看到在获取unsafe对象时会判断调用类是否是系统类加载器加载的,所以我们无法在自己的类中直接通过Unsafe.getUnsafe()获取unsafe对象。所以只能通过反射直接new一个或者将其内部静态成员变量theUnsafe获取出来
public static void main(String[] args) throws Exception{
    
    Class<Unsafe> unsafeClass = Unsafe.class;
    //方法一:通过反射构造一个Unsafe对象
    Constructor<Unsafe> constructor = unsafeClass.getDeclaredConstructor();
    constructor.setAccessible(true);
    Unsafe unsafe1 = constructor.newInstance();
    System.out.println(unsafe1);

    //方法二:获取内部静态成员变量
    Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
    theUnsafe.setAccessible(true);
    Unsafe unsafe2 = (Unsafe) theUnsafe.get(null);
    System.out.println(unsafe2);
}

三、CAS

CAS译为Compare And Swap,它是乐观锁的一种实现。假设主存值为pre,预期值为expect,想要更新成得值为update,当且仅当主存值pre等预期值expect时,才将pre更新为update。

1、相关方法

在unsafe中,实现CAS算法通过cpu的原子指令cmpxchg实现,它对应的方法如下:
在这里插入图片描述

简单介绍下它使用的参数:

  • 第一个参数 var1为内存中要操作的对象
  • 第二个参数 var2为要操作的值的内存地址偏移量
  • 第三个参数 var4为预期值
  • 第四个参数 var5 为想要更新成的值

为了方便理解,举个栗子。类User有一个成员变量name。我们new了一个对象User后,就知道了它(User对象)在内存中的起始值,而员变量name在对象中的位置偏移是固定的。这样通过这个起始值和这个偏移量就能够定位到成员变量name在内存中的具体位置。

如何得出name在对象User中的偏移量,Unsafe自然也提供了相应的方法:
在这里插入图片描述

2、demo

import sun.misc.Unsafe;
import java.lang.reflect.*;

public class UnsafeDemo {

    public static void main(String[] args) throws Exception {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);

        User user = new User("jsbintask");
        long nameOffset = unsafe.objectFieldOffset(User.class.getDeclaredField("name"));
        boolean res1 = unsafe.compareAndSwapObject(user, nameOffset, "jsbintask1", "jsbintask2");
        System.out.println(res1+", 第一次更新后的值:" + user.getName());
        boolean res2 = unsafe.compareAndSwapObject(user, nameOffset, "jsbintask", "jsbintask2");
        System.out.println(res2+", 第二次更新后的值:" + user.getName());
    }
    
    public static class User {
        private String name;
            public User(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
    }  
}

在这里插入图片描述
因为内存中name的值为"jsbintask",而第一次使用compareAndSwapObject方法预期值为"jsbintask1",这显然是不相等的,所以第一次更新失败,返回false。第二次我们传入了正确的预期值,返回true,更新成功!

四、数组操作

之后用到的时候再进行补充

五、内存分配

Unsafe还给我们提供了直接分配内存,释放内存,拷贝内存,内存设置等方法,值得注意的是,这里的内存指的是堆外内存!它是不受jvm内存模型掌控的,所以使用需要及其小心

在这里插入图片描述
之后用到的时候再进行补充

六、线程调度

通过Unsafe还可以直接将某个线程挂起,这和调用Object.wait()方法作用是一样的,但是效率确更高!
在这里插入图片描述
我们熟知的AQS(AbstractQueuedSynchronizer)内部挂起线程使用了LockSupport,而LockSupport内部依旧使用的是Unsafe:

之后用到的时候再进行补充

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/656071.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s 集群部署尝试

K8S 部署方式有很多&#xff0c;有的方式不太友好&#xff0c;需要注意很多关键点&#xff0c;有的方式对小白比较友好&#xff0c;部署简单方便且高效 二进制源码包的部署方式 使用 二进制源码包的方式部署会比较麻烦&#xff0c;大概分为如下几步&#xff1a; 获取源码包部…

基于abaqus的Huang晶体塑性UMAT改VUMAT

黄永刚院士编写的单晶晶体塑性UMAT&#xff0c;主要用于在Abaqus有限元仿真中进行单晶及多晶晶体塑性变形的计算&#xff0c;是许多科研工作者学习晶体塑性模拟的教学资源。可以在其基础上对硬化模型进行修改&#xff0c;甚至引入损伤。 UMAT主要应用于隐式分析&#xff0c;而…

力扣动态规划专题(二)01背包 416. 分割等和子集 1049.最后一块石头的重量II 494. 目标和 474. 一和零 步骤及C++实现

文章目录 01背包二维dp数组一维dp数组 滚动数组 416. 分割等和子集1049.最后一块石头的重量II494. 目标和474. 一和零 01背包 完全背包的物品数量是无限的&#xff0c;01背包的物品数量只有一个。 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xf…

基于ArcGIS的nc(NETCDF)转tif格式

软件版本&#xff1a;ArcMap10.4.1 nc(NETCDF)是一组独立于机器的软件库支持创建、访问和共享面向阵列的数据格式科学数据&#xff0c;它也是共享科学数据的社区标准。&#xff08;摘自Unidata官网&#xff09;&#xff0c;被广泛应用于大气、海洋、水文等领域&#xff0c;是我…

stm32读取BH1750光照传感器

stm32读取BH1750光照传感器 一.序言二.BH1750指令三.IIC协议四.代码实例4.1 bh1750.c源文件4.2 bh1750.h头文件 一.序言 BH1750是用IIC协议进行数据传输的。有SCL,SDA&#xff0c;VCC,GND四根线。下图是原理图 二.BH1750指令 我们先看芯片手册的操作指令&#xff08;下图&a…

直播 RTM 推流在抖音的应用与优化

动手点关注 干货不迷路 背景 随着互联网技术以及网络基建的快速发展和普及&#xff0c;视频直播已经成为了一种越来越普遍的娱乐和社交方式。无论是个人还是企业&#xff0c;都可以通过视频直播平台进行直播活动&#xff0c;向观众展示自己的生活、工作或者产品。同时&#xff…

有什么办法恢复格式后的u盘数据?5个方法,赶紧收藏起来

随着科技的不断进步&#xff0c;U盘已经成为了我们重要的移动存储设备之一&#xff0c;但是在使用过程中&#xff0c;很多人都可能会不小心将U盘格式化导致数据丢失。那么有什么办法恢复格式后的U盘数据&#xff1f;本文将会为您介绍恢复U盘格式化后数据的5种方法&#xff0c;如…

MT6761/MT6762/MT6765核心板模块 demo串口调试

串口调试 如果正在进行lk(little kernel ) 或内核开发&#xff0c;USB 串口适配器&#xff08; USB 转串口 TTL 适配器的简称&#xff09;对于检查系统启动日志非常有用&#xff0c;特别是在没有图形桌面显示的情况下。 1. 选购适配器 常用的许多 USB 转串口的适配器&#x…

SpringCloud:分布式事务Seata实践优化

1.极致性能优化 1.1. 同库模式 通常&#xff0c;一个TM会产生一笔主事务日志&#xff0c;一个RM会产生一条分支事务日志&#xff0c;每个分布式事务由一个TM和若干 RM组成&#xff0c;一个分布式事务总共会有1N条事务日志&#xff08;N为RM个数&#xff09;。 在默认情况下&…

万物的算法日记|第五天

笔者自述&#xff1a; 一直有一个声音也一直能听到身边的大佬经常说&#xff0c;要把算法学习搞好&#xff0c;一定要重视平时的算法学习&#xff0c;虽然每天也在学算法&#xff0c;但是感觉自己一直在假装努力表面功夫骗了自己&#xff0c;没有规划好自己的算法学习和总结&am…

CTFshow-pwn入门-前置基础pwn5 - pwn12

pwn5-pwn12的题目全是关于汇编语言的知识&#xff0c;pwn5-pwn12的汇编文件的代码都是一样的。 我们将可执行文件和汇编文件托到ctfshow-pwn专用虚拟机里&#xff0c;给可执行文件加上执行权限并查看其信息。 32位的&#xff0c;直接扔到ida中去。 在虚拟机中使用cat命令读取下…

SpringBoot的配置文件

SpringBoot的配置文件 &#x1f50e;配置文件的作用&#x1f50e;配置文件的格式&#x1f50e;properties配置文件properties的基本语法读取配置文件 &#x1f50e;yml配置文件yml的基本语法读取配置文件Tips关于 \n&#x1f36d;配置对象&#x1f36d;配置集合&#x1f36d; &…

网络知识点之-DNS协议

域名系统&#xff08;Domain Name System&#xff0c;缩写&#xff1a;DNS&#xff09;是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便地访问互联网。DNS使用TCP和UDP端口53。当前&#xff0c;对于每一级域名长度的限制是63个…

4.13 ReentrantLock

相对于 synchronized 它具备如下特点 可中断可以设置超时时间可以设置为公平锁支持多个条件变量 与 synchronized 一样&#xff0c;都支持可重入 基本语法// 获取锁reentrantLock.lock();try{// 临界区} finally{// 释放锁reentrantLock.unlock();}1、可重入 可重入是指同一个…

小程序 抽象节点 selectable 与slot区别

比较 了解了微信小程序的抽象节点组件封装方式之后&#xff0c;觉得与vue的slot使用类似&#xff0c;但也有些区别 &#xff1a; 抽象节点 和 slot 有什么不同&#xff1a; slot只需要你传入一段代码抽象节点需要你传入一个自定义组件&#xff0c;&#xff0c;不是让你只传递…

Kubernetes集群本地连接调试工具KtConnect

一、简介 KtConnect&#xff08;Kt为Kubernetes Toolkit集群工具包的简写&#xff09;是一款基于Kubernetes环境用于提高本地测试联调效率的小工具 Connect&#xff1a;建立数据代理通道&#xff0c;实现本地服务直接访问Kubernetes集群内网&#xff08;包括Pod IP和Service域…

Jetpack Compose教程-水位控制小部件

Jetpack Compose教程-水位控制小部件 Apple的应用程序和小部件一直是设计的典范&#xff0c;也给我们的"复制系列&#xff1a;活动应用"和"卡片应用"提供了灵感。当他们发布了新款苹果手表Ultra时&#xff0c;它里面深度测量小部件的设计引起了我们的兴趣&…

加快奔向“国际数字之都” CDEC2023中国数字智能生态大会走进上海

数智闪耀长三角&#xff0c;风云际会上海滩。 6月14日上午&#xff0c;以汇聚数字产业动能、打造区域合作为主旨的 CDEC2023中国数字智能生态大会上海站活动在浦东软件园创新体验中心举行。 大会以“共建AI智能生态”为主题&#xff0c;吸引致远互联、SAP、浪潮等龙头企业&…

2022年山东省职业院校技能大赛网络搭建与应用赛项网络搭建与安全部署服务器配置及应用

2022年山东省职业院校技能大赛 网络搭建与应用赛项 第二部分 网络搭建与安全部署&服务器配置及应用 竞赛说明&#xff1a; 一、竞赛内容分布 竞赛共分二个模块&#xff0c;其中&#xff1a; 第一模块&#xff1a;网络搭建及安全部署项目 第二模块&#xff1a;服务器…

C#里的var和dynamic区别到底是什么,你真的搞懂了嘛

前言 这个var和dynamic都是不确定的初始化类型&#xff0c;但是这两个本质上的不同。不同在哪儿呢?var编译阶段确定类型&#xff0c;dynamic运行时阶段确定类型。这种说法对不对呢&#xff1f;本篇看下,文章原文地址&#xff1a;在这里 概括 以下详细叙述下这两个(var,dynamic…