性能调优专题-基础-1、JVM-编译器、解释器、执行器
1. JVM编译器1.1. 前端编译器如javac,将java文件编译为class文件。此阶段不会发生指令重排序。 1.2. 后端编译器JIT 是将一些字节码编译为机器码,并存入 Code Cache,下次遇到相同的代码,直接执行,无需再编译。此阶段可能会发生指令重排序。 和解释器一样,起点都是编译后的 class 文件,而不是.java 源文件。 HotSpot中内置了两个即时编译器,分别称为 Client Compiler和 Server Compiler ,或者简称为 C1 编译器和 C2 编译器。目前的 HotSpot 编译器默认的是解释器和其中一个即时编译器配合的方式工作,具体是哪一个编译器,取决于虚拟机运行的模式,HotSpot 虚拟机会根据自身版本与计算机的硬件性能自动选择运行模式,用户也可以使用 -client 和 -server 参数强制指定虚拟机运行在 Client 模式或者 Server 模式。这种配合使用的方式称为“混合模式”(Mixed Mode),用户可以使用参数 -Xint 强制虚拟机运行于 “解释模式”(Interpreted Mode),这时候编译 ...
并发编程专题-基础-7、Thread
1. 实现2. 状态⭐️🔴 https://blog.51cto.com/u_15080031/4547025 2.1. 状态流转 结合线程状态解释一下执行过程。(状态装换参考自《深入理解 Java 虚拟机》) 新建(New),新建后尚未启动的线程 运行(Runnable),Runnable 包括了操作系统线程状态中的 Running 和 Ready 无限期等待(Waiting),不会被分配 CPU 执行时间,要等待被其他线程显式的唤醒。例如调用没有设置 Timeout 参数的 Object.wait() 方法 限期等待(Timed Waiting),不会被分配 CPU 执行时间,不过无需等待其他线程显示的唤醒,在一定时间之后会由系统自动唤醒。例如调用 Thread.sleep() 方法 阻塞(Blocked),线程被阻塞了,“阻塞状态”与“等待状态”的区别是:“阻塞状态”在等待获取着一个排他锁,这个事件将在另外一个线程放弃这个锁的时候发生,而“等待状态”则是在等待一段时间,或者唤醒动作的发生。在程序等待进入同步区域的时候,线程将进入这种状态 结束(Terminated):线程 ...
并发编程专题-基础-9、Java各种锁
1. Synchronized 8 锁问题⭐️🔴示例代码:[[Lock_8.java]] ❕%%0915-🏡⭐️◼️阿里规约🔜MSTM📝 能用对象锁就不用类锁。尽可能使得加锁代码块工作量变小,避免在锁块中调用 RPC 方法◼️⭐️-point-202301230915%% 12345678*1 标准访问,请问先打印邮件还是短信*2 暂停4秒钟在邮件方法,请问先打印邮件还是短信*3 新增普通sayHello方法,请问先打印邮件还是hello*4 两部手机,请问先打印邮件还是短信*5 两个静态同步方法,同一部手机,请问先打印邮件还是短信*6 两个静态同步方法,2部手机,请问先打印邮件还是短信*7 1个静态同步方法,1个普通同步方法,同一部手机,请问先打印邮件还是短信*8 1个静态同步方法,1个普通同步方法,2部手机,请问先打印邮件还是短信 1.1. 锁对象1.1.1. 情况 1 和 2⭐️🔴%%▶2.🏡⭐️◼️【🌈费曼无敌🌈⭐️第一步⭐️】◼️⭐️-point-20230512-1442%%❕ ^tcdpjx 锁的是==当前对象 this=& ...
并发编程专题-基础-8、Volatile
1. 简要回答 2. 乱序问题并发基础-11、乱序问题 3. 前置知识3.1. JMM 原子操作3.1.1. JMM 及 MESI请看 并发基础-1、JMM与MESI Volatile 保证了 JMM 三大特性的可见性和有序性,但无法保证原子性 (Synchronized 保证了可见性、有序性和原子性)。 3.2. 可见性3.2.1. 可见性原理 1、在对变量进行 assign 操作时,加了 Volatile 修饰的变量,计算机底层会加一个 lock 前缀指令(这个操作利用了 MESI 协议对 M 状态变量的处理逻辑,向总线发送 Invalid 信息,并立即写回主内存)。 2、同时,lock 前缀指令 有内存屏障的作用,在 assign 的时候就对变量施加了 缓存锁,防止读取未修改的数据。 3.2.2. JVM 源码实现bytecodeinterpreter.cpp 12345int field_offset = cache->f2_as_index(); if (cache->is_volatile()) { ...
Java基础-1、Java-相关名词
1. new Object() 2. 线程集合JVM 维护了一个集合存放所有存活的线程,通过遍历该集合判断某个线程是否存活。 3. 栈高低位[[../../../../cubox/006-ChromeCapture/20221112-内存栈分配从高到低为什么 - 墨天轮]] 4. JNDIhttps://www.cnblogs.com/wlzjdm/p/7856356.html 5. JCP JSR[[../../../../cubox/006-ChromeCapture/阿里巴巴入选的JCP最高执行委员会,何方神圣?_方向盘(YourBatman)的博客-CSDN博客]] 6. 深拷贝 (深克隆)设计模式-5、原型模式 https://juejin.cn/post/6844903693100417038https://juejin.cn/post/6986071906273198094 7. DO DTO AO VO BO POJO[[阿里巴巴Java开发手册中的 ...
并发编程专题-基础-6、CAS
1. JUC 中的 CAS1.1. 是什么 1.2. 底层原理1.2.1. 保证可见性 1.2.2. 保证原子性 1.3. 汇编实现 1.4. synchronized 中的 CAS1.4.1. Atomic::cmpxchg_ptr轻量级锁加锁的时候,如果处于无锁状态,则会通过 CAS 操作将锁对象的 Mark Word 更新为指向 Lock Record 的指针,相关代码如下: 12345678910if (mark->is_neutral()) { // Anticipate successful CAS -- the ST of the displaced mark must // be visible <= the ST performed by the CAS. lock->set_displaced_header(mark); if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) { TEVENT ...
并发编程专题-基础-4、信号量与管程
信号量 vs 管程并发编程这个技术领域已经发展了半个世纪了,相关的理论和技术纷繁复杂。那有没有一种核心技术可以很方便地解决我们的并发问题呢?事实上,锁机制的实现方案有两种: **信号量(Semaphere)**:操作系统提供的一种协调共享资源访问的方法。和用软件实现的同步比较,软件同步是平等线程间的的一种同步协商机制,不能保证原子性。而信号量则由操作系统进行管理,地位高于进程,操作系统保证信号量的原子性。 **管程(Monitor)**:解决信号量在临界区的 PV 操作上的配对的麻烦,把配对的 PV 操作集中在一起,生成的一种并发编程方法。其中使用了条件变量这种同步机制。 说明: 信号量将共享变量 S 封装起来,对共享变量 S 的所有操作都只能通过 PV 进行,这是不是和面向对象的思想是不是很像呢?事实上,封装共享变量是并发编程的常用手段。 在信号量中,当 P 操作无法获取到锁时,将当前线程添加到**同步队列(syncQueue)中。当其余线程 V 释放锁时,从同步队列中唤醒等待线程。但当有多个线程通过信号量 PV 配对时会异常复杂,所以管程中引入了等待队列(waitQueue) ...
并发编程专题-基础-5、进程 线程 纤程 协程 管程
线程 线程模型[[java线程模型 不忘初心方得始终]] 一句话总结:Java 的线程是映射到操作系统的原生线程之上的。 JVM 没有限定 Java 线程需要使用哪种线程模型来实现, JVM 只是封装了底层操作系统的差异,而不同的操作系统可能使用不同的线程模型,例如 Linux 和 windows 可能使用了一对一模型,solaris 和 unix 某些版本可能使用多对多模型。所以一谈到 Java 语言的多线程模型,需要针对具体 JVM 实现。 比如 Sun JDK 1.2 开始,线程模型都是基于操作系统原生线程模型来实现,它的 Window 版和 Linux 版都是使用系统的 1:1 的线程模型实现的。 参考https://www.bilibili.com/video/BV1yL4y1B7za/?spm_id_from=333.337.search-card.all.click&vd_source=c5b2d0d7bc377c0c35dbc251d95cf204 [[../../../../cubox/006-ChromeC ...
并发编程专题-基础-3、对象内存
1. OOP-Klass 模型这里的 Oop 并非是 Object-oriented programming,而是 Ordinary object pointer(普通对象指针),是 HotSpot 用来表示 Java 对象的实例信息的一个体系。其中 oop 是 Oop 体系中的最高父类,整个继承体系如下所示: https://juejin.cn/post/6844904054561193992 1.1. JVM 实现⭐️🔴^phycx3 JVM 在加载 class 时,通过类的全限定名获取存储该类的 class 文件,创建 instanceKlass,表示其元数据,存放在方法区;并在堆区生成该类的 Class 对象,即 instanceMirrorKlass 对象。 在 new 一个对象时,JVM 创建 instanceOopDesc,来表示这个对象,存放在堆区;它用来表示对象的实例信息,看起来像个指针实际上是藏在指针里的对象;instanceOopDesc 对应 java 中的对象实例 HotSpot 并不把 instanceKlass 暴露给 Java,而会另外创建对应的 j ...
并发编程专题-基础-1、JMM与MESI
1. CPU 架构1.1. CPU 主要架构 1.1.1. Front End(Core 前端)首先看 Front-end,Front-end 的主要目的就是从内存里提取各种各样的 X86 指令,然后对指令进行译码,融合优化等操作,把 X86 指令转化为最适合执行单元执行的微指令流传递给执行单元。Front-End 的存在就是为了让执行单元时刻保持繁忙,将 CPU 的性能完全发挥出来。 1.1.1.1. 乱序组件 **Allocation Queue(IDQ): 分配队列,分配队列作为前端与执行单元的接口,是 Core 前端的最后的一个部件。分配队列的目的是将微指令进行重新整合与融合,发给执行单元进行乱序执行。分配队列又包含了 Loop Stream Detector(LSD) 循环流检测器,对循环操作进行优化与 up-Fusion(微指令融合单元)。融合是为了让后续解码单元更有效率并且节省 ROB(re-order buffer)的空间 1.1.2. Execution Engine (执行单元)Front-End 的存在就是为了让执行单元时刻保持繁忙,那么执行单元的最主要 ...

