java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作,主要提供了以下功能:

1、通过Unsafe类可以分配内存,可以释放内存;

类中提供的3个本地方法allocateMemory、reallocateMemory、freeMemory分别用于分配内存,扩充内存和释放内存,与C语言中的3个方法对应。

2、可以定位对象某字段的内存位置,也可以修改对象的字段值,即使它是私有的;

  1. public native long allocateMemory(long l);
  2. public native long reallocateMemory(long l, long l1);
  3. public native void freeMemory(long l);
字段的定位:
JAVA中对象的字段的定位可能通过staticFieldOffset方法实现,该方法返回给定field的内存地址偏移量,这个值对于给定的filed是唯一的且是固定不变的。
getIntVolatile方法获取对象中offset偏移地址对应的整型field的值,支持volatile load语义。
getLong方法获取对象中offset偏移地址对应的long型field的值
数组元素定位:
Unsafe类中有很多以BASE_OFFSET结尾的常量,比如ARRAY_INT_BASE_OFFSET,ARRAY_BYTE_BASE_OFFSET等,这些常量值是通过arrayBaseOffset方法得到的。arrayBaseOffset方法是一个本地方法,可以获取数组第一个元素的偏移地址。Unsafe类中还有很多以INDEX_SCALE结尾的常量,比如 ARRAY_INT_INDEX_SCALE
, ARRAY_BYTE_INDEX_SCALE等,这些常量值是通过arrayIndexScale方法得到的。arrayIndexScale方法也是一个本地方法,可以获取数组的转换因子,也就是数组中元素的增量地址。将arrayBaseOffset与arrayIndexScale配合使用,可以定位数组中每个元素在内存中的位置。
  1. public final class Unsafe {
  2. public static final int ARRAY_INT_BASE_OFFSET;
  3. public static final int ARRAY_INT_INDEX_SCALE;
  4. public native long staticFieldOffset(Field field);
  5. public native int getIntVolatile(Object obj, long l);
  6. public native long getLong(Object obj, long l);
  7. public native int arrayBaseOffset(Class class1);
  8. public native int arrayIndexScale(Class class1);
  9. static
  10. {
  11. ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset([I);
  12. ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale([I);
  13. }
  14. }

3、挂起与恢复

将一个线程进行挂起是通过park方法实现的,调用 park后,线程将一直阻塞直到超时或者中断等条件出现。unpark可以终止一个挂起的线程,使其恢复正常。整个并发框架中对线程的挂起操作被封装在 LockSupport类中,LockSupport类中有各种版本pack方法,但最终都调用了Unsafe.park()方法。
  1. public class LockSupport {
  2. public static void unpark(Thread thread) {
  3. if (thread != null)
  4. unsafe.unpark(thread);
  5. }
  6. public static void park(Object blocker) {
  7. Thread t = Thread.currentThread();
  8. setBlocker(t, blocker);
  9. unsafe.park(false, 0L);
  10. setBlocker(t, null);
  11. }
  12. public static void parkNanos(Object blocker, long nanos) {
  13. if (nanos > 0) {
  14. Thread t = Thread.currentThread();
  15. setBlocker(t, blocker);
  16. unsafe.park(false, nanos);
  17. setBlocker(t, null);
  18. }
  19. }
  20. public static void parkUntil(Object blocker, long deadline) {
  21. Thread t = Thread.currentThread();
  22. setBlocker(t, blocker);
  23. unsafe.park(true, deadline);
  24. setBlocker(t, null);
  25. }
  26. public static void park() {
  27. unsafe.park(false, 0L);
  28. }
  29. public static void parkNanos(long nanos) {
  30. if (nanos > 0)
  31. unsafe.park(false, nanos);
  32. }
  33. public static void parkUntil(long deadline) {
  34. unsafe.park(true, deadline);
  35. }
  36. }

4、CAS操作

是通过compareAndSwapXXX方法实现的
  1. /**
  2. * 比较obj的offset处内存位置中的值和期望的值,如果相同则更新。此更新是不可中断的。
  3. *
  4. * @param obj 需要更新的对象
  5. * @param offset obj中整型field的偏移量
  6. * @param expect 希望field中存在的值
  7. * @param update 如果期望值expect与field的当前值相同,设置filed的值为这个新值
  8. * @return 如果field的值被更改返回true
  9. */
  10. public native boolean compareAndSwapInt(Object obj, long offset, int expect, int update);
CAS操作有3个操作数,内存值M,预期值E,新值U,如果M==E,则将内存值修改为B,否则啥都不做。

参考资料:

JAVA并发编程学习笔记之Unsafe类的更多相关文章

  1. [转]JAVA并发编程学习笔记之Unsafe类

    1.通过Unsafe类可以分配内存,可以释放内存:类中提供的3个本地方法allocateMemory.reallocateMemory.freeMemory分别用于分配内存,扩充内存和释放内存,与C语 ...

  2. Java并发编程学习笔记

    Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...

  3. Java 并发编程学习笔记 理解CLH队列锁算法

    CLH算法实现 CLH队列中的结点QNode中含有一个locked字段,该字段若为true表示该线程需要获取锁,且不释放锁,为false表示线程释放了锁.结点之间是通过隐形的链表相连,之所以叫隐形的链 ...

  4. Java并发编程学习笔记 深入理解volatile关键字的作用

    引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识.网上关于volatile的 ...

  5. Java并发编程学习笔记(一)——线程安全性

    主要概念:线程安全性.原子性.原子变量.原子操作.竟态条件.复合操作.加锁机制.重入.活跃性与性能. 1.当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变 ...

  6. JAVA并发编程学习笔记------多线程调优

    1. 多线程场景下尽量使用并发容器代替同步容器 (如ConcurrentHashMap代替同步且基于散列的Map, 遍历操作为主要操作的情况下用CopyOnWriteArrayList代替同步的Lis ...

  7. JAVA并发编程学习笔记------基础构建模块

    一.并发容器:ConcurrentHashMap:1.分段锁机制: 任意数量的读取线程可以并发的访问map,执行读取操作的线程和执行写入操作的线程可以并发的访问Map,并且一定数量的写入线程可以并发的 ...

  8. JAVA并发编程学习笔记------对象的可见性及发布逸出

    一.非原子的64位操作: 当线程在没有同步的情况下读取变量时,可能会得到一个失效值,但至少这个值是由之前某个线程设置的值,而不是一个随机值,这种安全性保证被称为最低安全性.最低安全性适用于绝大多数变量 ...

  9. Java并发编程学习笔记(三)——对象的组合

    重要概念: 1.在设计线程安全类的过程中,需要包含以下三个基本要素: (1)找出构成对象状态的所有变量. (2)找出约束状态变量的不变性条件. (3)建立对象状态的并发访问管理策略. 2.

  10. Java并发编程学习笔记(二)——对象的共享

    主要概念:可见性.重排序.失效数据.最低安全性.发布.逸出.线程封闭(Ad-hoc.栈封闭.ThreadLocal类).不变性.Final域.事实不可变对象. 1.在没有同步的情况下,编译器.处理器以 ...

随机推荐

  1. 【YashanDB知识库】ycm托管数据库时报错OM host ip:127.0.0.1 is not support join to YCM

    问题现象 托管数据库时检查报错OM的IP是127.0.0.1,不支持托管到YCM OM 问题的风险及影响 导致数据库无法托管监控 问题影响的版本 问题发生原因 安装数据库时修改了OM的监听ip为127 ...

  2. 丝滑解决Chatgpt频繁奔溃、断网掉线问题

    事件缘由 这段时间使用Chatgpt的时候频繁出现something wrong等断网掉线问题,中间还频繁出现物品转向的人机验证(我那么具有迷惑性吗...),被烦的不行.后面了解到有一个KeepCha ...

  3. github代理加速

    终端命令行 支持终端命令行 git clone , wget , curl 等工具下载.支持 raw.githubusercontent.com , gist.github.com , gist.gi ...

  4. React函数式组件避免无用渲染的方案

    在class组件中可以使用shouldComponentUpdate钩子函数,但是函数式组件中是没有这种钩子函数的,那么在函数式组件中来达到类似的效果呢? 答案是:React.Memo,如以下使用案例 ...

  5. ZEGO 教程 | RTC + AI 视觉的最佳实践(移动端)

    ​  ​摘要:帮助开发者在音视频场景中快速获得 AI 视觉功能 -- 美颜.滤镜.背景抠图等. 文|即构 Native SDK 开发团队 Z世代作为社会新的消费主力,追求个性.热爱新奇事物,青睐与酷炫 ...

  6. EF Core – Table / Entity Splitting

    参考 Docs – Advanced table mapping Table Splitting Table Splitting 指的是把一个表映射到多个 Entity,或者反过来说就是把多个 Ent ...

  7. DOM – Web Animation API

    前言 以前写过相关的文章 angular2 学习笔记 ( animation 动画 ).但在项目种很少用到 Web Animation. 体会不到它的精髓,目前的感觉是,它对比 CSS Animati ...

  8. @RestController和@Controller的区别

    @RestController 和 @Controller 是Spring框架中用于定义控制器(Controller)的两个非常重要的注解,它们都用于处理HTTP请求,但它们之间存在一些关键的区别. ...

  9. Kubernetes ReplicaSet 控制器(十九)

    前面我们一起学习了 Pod 的原理和一些基本使用,但是在实际使用的时候并不会直接使用 Pod,而是会使用各种控制器来满足我们的需求,Kubernetes 中运行了一系列控制器来确保集群的当前状态与期望 ...

  10. threejs - 渲染第一个3D场景 - 旋转的正方体

    1. 安装 threejs & 使用 2. 创建三要素  场景 scene 相机 camera 渲染器 render 3. 场景 new THREE.Scene() 相机分为 2 种  1. ...