并发系列-第3章-并发设计模式
28 | Immutability模式:如何利用不变性解决并发问题?“多个线程同时读写同一共享变量存在并发问题”,这里的必要条件之一是读写,如果只有读,而没有写,是没有并发问题的。 不变性,简单来讲,就是对象一旦被创建之后,状态就不再发生变化 换句话说,就是变量一旦被赋值,就不允许修改了(没有写操作);没有修改操作,也就是保持了不变性。 实现一个具备不可变性的类,还是挺简单的。将一个类所有的属性都设置成 final 的,并且只允许存在只读方法,那么这个类基本上就具备不可变性了。更严格的做法是这个类本身也是 final 的,也就是不允许继承。因为子类可以覆盖父类的方法,有可能改变不可变性 Java SDK 里很多类都具备不可变性,例如经常用到的 String 和 Long、Integer、Double 等基础类型的包装类都具备不可变性,这些对象的线程安全性都是靠不可变性来保证的。 类和属性都是 final 的,所有方法均是只读的。 如果具备不可变性的类,需要提供类似修改的功能,具体该怎么操作呢?做法很简单,那就是创建一个新的不可变对象 所有的修改操作都创建一个新的不可变对象,你可能会有这 ...
并发系列-第2章-并发工具类
14 | Lock和Condition(上):隐藏在并发包中的管程Java SDK 并发包通过 Lock 和 Condition 两个接口来实现管程,其中 Lock 用于解决互斥问题,Condition 用于解决同步问题。 再造管程的理由synchronized 无法解决死锁问题 synchronized 申请资源的时候,如果申请不到,线程直接进入阻塞状态了,而线程进入阻塞状态,啥都干不了,也释放不了线程已经占有的资源。 新设计一把互斥锁去解决这个问题 能够响应中断。synchronized 的问题是,持有锁 A 后,如果尝试获取锁 B 失败,那么线程就进入阻塞状态,一旦发生死锁,就没有任何机会来唤醒阻塞的线程。但如果阻塞状态的线程能够响应中断信号,也就是说当我们给阻塞的线程发送中断信号的时候,能够唤醒它,那它就有机会释放曾经持有的锁 A。这样就破坏了不可抢占条件了。 支持超时。如果线程在一段时间之内没有获取到锁,不是进入阻塞状态,而是返回一个错误,那这个线程也有机会释放曾经持有的锁。这样也能破坏不可抢占条件。 非阻塞地获取锁。如果尝试获取锁失败,并不进入阻塞状态,而是直接返回,那这 ...
并发系列-第1章-并发理论基础
《Java并发编程的艺术》 https://bolg2022.oss-cn-hangzhou.aliyuncs.com/202205192237090.pdf 01 | 可见性、原子性和有序性问题:并发编程Bug的源头源头之一:缓存导致的可见性问题在单核时代,所有的线程都是在一颗 CPU 上执行,CPU 缓存与内存的数据一致性容易解决。因为所有线程都是操作同一个 CPU 的缓存,一个线程对缓存的写,对另外一个线程来说一定是可见的。例如在下面的图中,线程 A 和线程 B 都是操作同一个 CPU 里面的缓存,所以线程 A 更新了变量 V 的值,那么线程 B 之后再访问变量 V,得到的一定是 V 的最新值(线程 A 写过的值)。 一个线程对共享变量的修改,另外一个线程能够立刻看到,我们称为可见性。 多核时代,每颗 CPU 都有自己的缓存,这时 CPU 缓存与内存的数据一致性就没那么容易解决了,当多个线程在不同的 CPU 上执行时,这些线程操作的是不同的 CPU 缓存。比如下图中,线程 A 操作的是 CPU-1 上的缓存,而线程 B 操作的是 CPU-2 上的缓存,很明显,这个时候线程 ...
JVM系列-第22章-JVM监控及诊断工具
JVM监控及诊断工具jps:查看正在运行的 Java 进程基本情况jps(Java Process Status):显示指定系统内所有的 HotSpot 虚拟机进程(查看虚拟机进程信息),可用于查询正在运行的虚拟机进程。 基本语法1jps [options] [hostid] options 参数 12345-q:仅仅显示 LVMID(local virtual machine id),即本地虚拟机唯一 ID。不显式主类的名称等-l:输出应用程序主类的全类名或如果进程执行的是 jar 包,则输出 jar 完整路径-m:输出虚拟机进程启动时传递给主类 main() 的参数-v:列出虚拟机进程启动时的 JVM 参数。比如:-Xms20m -Xmx50m 是启动程序指定的 JVM 参数补充:如果某 Java 进程关闭了默认开启的 UsePerfData 参数(即使用参数 -XX:-UsePerfData),那么 jps 命令(以及下面介绍的 jstat)将无法探知该 Java 进程。 hostid 参数 RMI 注册表中注册的主机名。 如果想要远程监控主机上的 Java 程序,需要安装 ...
JVM系列-第21章-性能调优
性能调优概述大厂面试题支付宝: 1支付宝三面:JVM 性能调优都做了些什么? 小米: 12有做过 JVM 内存优化吗?从 SQL、JVM、架构、数据库四个方面讲讲优化思路 蚂蚁金服: 12345JVM 的编译优化JVM 性能调优都做了什么?JVM 诊断调优工具用过哪些?二面:JVM 怎样调优,堆内存、栈空间设置多少合适?三面:JVM 相关的分析工具使用过的有哪些?具体的性能调优步骤是什么? 阿里: 12如何进行 JVM 调优?有哪些方法?如何理解内存泄漏问题?有哪些情况会导致内存泄漏?如何解决? 字节跳动: 1三面:JVM 如何调优、参数怎么调? 拼多多: 1从 SQL、JVM、架构、数据库四个方面讲讲优化思路 京东: 12345JVM 诊断调优工具用过哪些?每秒几十万并发的秒杀系统为什么会频繁发生 GC?日均百万级交易系统如何优化 JVM?线上生产系统 OOM 如何监控及定位与解决?高并发系统如何基于 G1 垃圾回收器优化性能? 背景说明生产环境中的问题 生产环境繁盛了内存溢出该如何处理? 生产环境应该给服务器分配多少内存合适? 如何对垃圾回收器的性能进行调优? 生产环 ...
JVM系列-第20章-类的加载器
再谈类的加载器概述类加载器是 JVM 执行类加载机制的前提。 ClassLoader 的作用: ClassLoader 是 Java 的核心组件,所有的 Class 都是由 ClassLoader 进行加载的,ClassLoader 负责通过各种方式将 Class 信息的二进制数据流读入 JVM 内部,转换为一个与目标类对应的 java.lang.Class 对象实例。然后交给 Java 虚拟机进行链接、初始化等操作。因此,ClassLoader 在整个装载阶段,只能影响到类的加载,而无法通过 ClassLoader 去改变类的链接和初始化行为。至于它是否可以运行,则由 Execution Engine 决定。 大厂面试题蚂蚁金服: 深入分析 ClassLoader,双亲委派机制 类加载器的双亲委派模型是什么? 一面:双亲委派机制及使用原因 百度: 都有哪些类加载器,这些类加载器都加载哪些文件? 手写一个类加载器 Demo Class 的 forName("java.lang.String") 和 Class 的 getClassLoader() 的 loadCl ...
JVM系列-第19章-类的加载过程详解
类的加载过程详解概述在 Java 中数据类型分为基本数据类型和引用数据类型。基本数据类型由虚拟机预先定义,引用数据类型则需要进行类的加载。 按照 Java 虚拟机规范,从 Class 文件到加载到内存中的类,到类卸载出内存位置,它的整个生命周期包括如下七个阶段: 其中,验证、准备、解析 3 个部分统称为链接(Linking)。 大厂面试题蚂蚁金服: 描述一下 JVM 加载 Class 文件的原理机制? 一面:类加载过程 百度: 类加载的机制 Java 类加载过程? 简述 Java 类加载机制? 腾讯: JVM 中类加载机制,类加载过程? 滴滴: JVM 类加载机制 美团: Java 类加载过程 描述一下 JVM 加载 Class 文件的原理机制 过程一:Loading(加载)阶段加载完成的操作加载的理解所谓加载,简而言之就是将 Java 类的字节码文件加载到机器内存中,并在内存中构建出 Java 类的原型——类模板对象。所谓类模板对象,其实就是 Java 类在 JVM 内存中的一个快照,JVM 将从字节码文件中解析出的常量池、类字段、类方法等信息存储到模板中,这样 JVM 在运行期便 ...
JVM系列-第18章-字节码指令集与解析举例
字节码指令集与解析举例// todo 记:2022/05/17
JVM系列-第17章-Class文件结构
Class 文件结构概述字节码文件的跨平台性Java 语言,跨平台的(write once,run anywhere) 当 Java 源代码成功编译成字节码后,如果想在不同的平台上面运行,则无须再次编译。 这个优势不再那么吸引人了。Python、PHP、Perl、Ruby、Lisp 等有强大的解释器。 跨平台似乎已经快称为一门语言必选的特性。 Java 虚拟机:跨语言的平台 Java 虚拟机不和包括 Java 在内的任何语言绑定,它只与”Class 文件”这种特定的二进制文件格式所关联。无论使用何种语言进行软件开发, 只要能将源文件编译为正确的 Class 文件,那么这种语言就可以在 Java 虚拟机上执行,可以说,统一而强大的 Class 文件结构,就是 Java 虚拟机的基石、桥梁。 https://docs.oracle.com/javase/specs/index.html 所有的 JVM 全部遵守 Java 虚拟机规范,也就是说所有的 JVM 环境都是一样的, 这样一来字节码文件可以在各种 JVM 上进行。 想要让一个 Java 程序正确地运行在 JVM 中,Java ...
JVM系列-第15章-垃圾回收相关概念
垃圾回收相关概念内存溢出javadoc中对OutofMemoryError的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存。 首先说没有空闲内存的情况:说明Java虚拟机的堆内存不够。原因有二: Java虚拟机的堆内存设置不够。 比如:可能存在内存泄漏问题;也很有可能就是堆的大小不合理,比如我们要处理比较可观的数据量,但是没有显式指定JVM堆大小或者指定数值偏小。我们可以通过参数-Xms 、-Xmx来调整。 代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用) 内存泄漏严格来说,只有对象不会再被程序用到了,但是GC又不能回收他们的情况,才叫内存泄漏。 但实际情况很多时候一些不太好的实践(或疏忽)会导致对象的生命周期变得很长甚至导致00M,也可以叫做宽泛意义上的“内存泄漏”。 尽管内存泄漏并不会立刻引起程序崩溃,但是一旦发生内存泄漏,程序中的可用内存就会被逐步蚕食,直至耗尽所有内存,最终出现outofMemory异常,导致程序崩溃。 买房子:80平的房子,但是有10平是公摊的面积,我们是无法使用这10平的空间,这就是所谓的内存泄漏 Java使用可达性 ...