Unsafe类的使用

news/2024/10/19 11:57:04/

目录

    • 一、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.ppmy.cn/news/433131.html

相关文章

对耳朵伤害最小的耳机类型,列举几款不入耳的骨传导耳机

骨传导耳机是最近几年火爆起来的耳机&#xff0c;它是将声音转化为不同频率的机械振动&#xff0c;通过人的颅骨、骨迷路、内耳淋巴液、螺旋器、听神经、听觉中枢来传递声波。与普通耳机相比最大的区别是声音不经过外耳道&#xff0c;避免了耳道长时间堵塞导致的中耳炎疾病发生…

4.13 ReentrantLock

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

串口协议说明

文章目录 波特率概念波特率相对误差UART误差保证 协议常见的串行接口协议之间的比较USB 转串口PL2303USB 转串口CP2102USB转232 串口电平TTL电平485电平 帧奇偶校验 波特率 概念 波特率的概念请点我 波特率相对误差 波特率的相对误差要小于4%或者5%。不会影响数据的正常接收…

【cutlass】cuTe layout操作

简介 cuTe提供了对Layout操作的算法&#xff0c;可以混合执行来构建更复杂的Layout操作&#xff0c;比如在其他layout之间切分和平铺layout 在host或者device上打印cuTe cuTe的打印函数可以在host和device端打印。cute::print 重载了几乎所有 CuTe 类型&#xff0c;包括指针…

k8s 集群部署尝试

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

深入了解模板知识(c++)

前言 在c中模板是很重的&#xff0c;泛型编程就是模板最好的体现&#xff0c;模板的出现就是为了更好的复用代码&#xff0c;有了它&#xff0c;我们不必写各种逻辑相同只是逻辑中的数据的类型的不同的代码&#xff0c;使得我们编写代码变得更加高效&#xff0c;下面让我们一起…

哪个星座的心肠最硬?

了解查询星座运势&#xff0c;关注“去问”就可以了。善良是一种优秀的品质&#xff0c;但有时候太过善良反而会成为被人利用的软肋&#xff0c;此时就需要学着让自己的心肠变硬&#xff0c;并且变得更加坚毅才不会被人欺负。那么&#xff0c;在十二星座中&#xff0c;有哪些星…

涌html编写星空图,canvas实现十二星座星空图

效果如下&#xff1a; 代码如下&#xff1a;canvas星座 * { margin: 0; padding: 0; } #box{ margin:10px 0 0 10px;; } input{ outline: none; font-size:16px; } p{ margin-bottom: 10px } input[typedate]{ height:36px; text-indent:10px; } input[typebutton]{ background…