CAS

【JVM之内存与垃圾回收篇】对象实例化内存布局与访问定位

a 夏天 提交于 2020-08-09 06:47:13
对象实例化内存布局与访问定位 从各自具体的 内存分配 上来讲 new 的对象放在 堆 中 对象所属的类型信息是放在 方法区 的 方法当中的局部变量放在 栈空间 这 new 的对象怎么把三块粘合到一起 就是这章的内容了 对象实例化 面试题 美团: 对象在 JVM 中是怎么存储的? 对象头信息里面有哪些东西? 蚂蚁金服: 二面 Java 对象头有什么? 从对象创建的方式和步骤开始说 对象创建方式 new:最常见的方式,单例类中调用 getInstance 的静态类方法,XXXFactory 的静态方法 Class 的 newInstance 方法:反射的方式,在 JDK9 里面被标记为过时的方法,因为只能调用空参构造器,权限必须是 public Constructor 的 newInstance(XXX):反射的方式,可以调用空参、带参的构造器,权限没有要求 使用 clone() :不调用任何的构造器,要求当前类需要实现 Cloneable 接口中的 clone() 方法 使用反序列化:反序列化一般用于 Socket 的网络传输,从文件中、从网络中获取一个对象的二进制流 第三方库 Objenesis 创建对象的步骤 判断对象对应的类是否加载、链接、初始化 虚拟机遇到一条 new 指令,首先去检查这个指令的参数能否在 Metaspace 的常量池中定位到一个类的符号引用

Striped64、LongAdder、LongAccumulator 源码分析

北城余情 提交于 2020-08-09 06:39:46
Striped64、LongAdder、LongAccumulator 源码分析 LongAdder 的作者是Doug Lea大神,该类原本在Guava工具包中,后来被Java8吸收,以下源码基于Java8 LongAdder 继承自Striped64,并实现了Serializable序列化接口。 Striped64 继承自Number,重写了longValue,intValue,floatValue,doubleValue Striped64 设计思路 该类提供一个Cell数组,和一个base字段,在多线程情况,让线程去竞争不同的Cell,而不是像AtomicLong去竞争更新同一个原子量。数组索引使用线程的哈希值 Cell数组的长度根据竞争程度,进行扩容,长度为$2^n$(n为原数组长度),扩容后不会缩小 通过Celll类的@Contended注解,避免了CPU Cache伪共享问题。 Cell //Contended注解防止CPU 缓存行伪共享 @sun.misc.Contended static final class Cell { //存放Cell中的具体值,volatile保证可见性 volatile long value; //Cell构造方法 Cell(long x) { value = x; } //cas更新操作,保证原子性,cmp期望值,val新值 final

从源码角度彻底理解ReentrantLock(重入锁)

走远了吗. 提交于 2020-08-09 05:03:42
目录 2.AbstractQueuedSynchronizer介绍 2.1 AQS是构建同步组件的基础 2.2 AQS的内部结构(ReentrantLock的语境下) 2.2.1 同步等待队列 2.2.2 AQS中的其他数据结构(ReentrantLock的语境下) 3 非公平模式加锁流程 3.1加锁流程真正意义上的入口 3.2 尝试获取锁的通用方法:tryAcquire() 3.3 获取锁失败的线程如何安全的加入同步队列:addWaiter() 3.4 线程加入同步队列后会做什么:acquireQueued() 3.5 加锁流程源码总结 4.非公平模式解锁流程 4.1 解锁流程源码解读 4.2 解锁流程源码总结 5. 公平锁相比非公平锁的不同 6. 一些疑问的解答 6.1 为什么基于FIFO的同步队列可以实现非公平锁? 6.2 为什么非公平锁性能好 7. 阅读源码的收获 在 ReentrantLock(重入锁)功能详解和应用演示 这篇文章里我们讲解并演示了ReentrantLock(重入锁)的各种功能,其中就谈到ReentrantLock可以有公平锁和非公平锁的不同实现,只要在构造它的时候传入不同的布尔值,继续跟进下源码我们就能发现,关键在于实例化内部变量 sync 的方式不同,如下所示 /** * Creates an instance of {@code

精选BAT Java面试突击1000道面试题详解:JVM篇.建议收藏

别来无恙 提交于 2020-08-08 21:49:49
JVM Java内存区域 说一下 JVM 的主要组成部分及其作用? 说一下 JVM 运行时数据区 深拷贝和浅拷贝 说一下堆栈的区别? 队列和栈是什么?有什么区别? HotSpot虚拟机对象探秘 对象的创建 为对象分配内存 处理并发安全问题 对象的访问定位 句柄访问 直接指针 内存溢出异常 Java会存在内存泄漏吗?请简单描述 垃圾收集器 简述Java垃圾回收机制 GC是什么?为什么要GC 垃圾回收的优点和原理。并考虑2种回收机制 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收? Java 中都有哪些引用类型? 怎么判断对象是否可以被回收? 在Java中,对象什么时候可以被垃圾回收 JVM中的永久代中会发生垃圾回收吗 说一下 JVM 有哪些垃圾回收算法? 标记-清除算法 复制算法 标记-整理算法 分代收集算法 说一下 JVM 有哪些垃圾回收器? 详细介绍一下 CMS 垃圾回收器? 新生代垃圾回收器和老年代垃圾回收器都有哪些?有什么区别? 简述分代垃圾回收器是怎么工作的? 内存分配策略 简述java内存分配与回收策率以及Minor GC和Major GC 对象优先在 Eden 区分配 大对象直接进入老年代 长期存活对象将进入老年代 虚拟机类加载机制 简述java类加载机制? 描述一下JVM加载Class文件的原理机制 什么是类加载器

JAVA并发编程关于锁的那些事,ReentantLock的底层设计深入浅出

試著忘記壹切 提交于 2020-08-08 14:20:56
一、介绍JUC java.util.concurrent是在并发编程中比较常用的工具类,里面包含很多用来在并发场景中使用的组件。比如 线程池、阻塞队列、计时器、同步器、并发集合 等等。 二、介绍Lock Lock最为重要的特性就是解决并发程序的安全性问题。 在JUC大部分组件都使用了Lock,所以了解和使用Lock显得尤为重要。Lock在JUC中本质上是以一个接口的形势表现的。 我们可以从上面的图中可以看出关于锁有很多不同的实现类。下面来简单介绍一翻吧。 2.1 ReentrantLock(重入锁) ReentrantLock实现了Lock接口,表示重入锁。是线程在获得锁之后,再次获取锁不需要阻塞,而是直接关联一次计数器增加重入次数。 后面我们重点分析ReentrantLock的原理。 2.2 ReentrantReadWriteLock(重入读写锁) ReentrantReadWriteLock实现了ReadWriteLock接口,其中有两把锁,一个 ReadLock ,一个 WriteLock ,它们分别实现了 Lock 接口。 适合读多写少的场景。 基本原则: 读和读不互斥; 读和写互斥; 写和写互斥。 2.3 StampedLock(改进版读写锁) StampedLock是JDK1.8引进的新的锁机制,它是读写锁的一个改进版。一种乐观的读策略,使得乐观锁完全不阻塞写线程。

Java锁有哪些种类,以及区别(转)

岁酱吖の 提交于 2020-08-08 12:53:02
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释。 公平锁/非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁。 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。 对于Java ReentrantLock 而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。 对于 Synchronized 而言,也是一种非公平锁。由于其并不像 ReentrantLock 是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。 可重入锁 可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。说的有点抽象,下面会有一个代码的示例。 对于Java ReentrantLock 而言, 他的名字就可以看出是一个可重入锁,其名字是 Re entrant Lock 重新进入锁。 对于 Synchronized 而言,也是一个可重入锁

你有认真了解过自己的“Java对象”吗? 渣男

天涯浪子 提交于 2020-08-08 12:36:58
对象在 JVM 中是怎么存储的 对象头里有什么? 文章收录在 GitHub JavaKeeper ,N线互联网开发必备技能兵器谱,有你想要的。 作为一名 Javaer,生活中的我们可能暂时没有对象,但是工作中每天都会创建大量的 Java 对象,你有试着去了解下自己的“对象”吗? 我们从四个方面重新认识下自己的“对象” 创建对象的 6 种方式 创建一个对象在 JVM 中都发生了什么 对象在 JVM 中的内存布局 对象的访问定位 一、创建对象的方式 使用 new 关键字 这是创建一个对象最通用、常规的方法,同时也是最简单的方式。通过使用此方法,我们可以调用任何要调用的构造函数(默认使用无参构造函数) Person p = new Person(); 使用 Class 类的 newInstance(),只能调用空参的构造器,权限必须为 public //获取类对象 Class aClass = Class.forName("priv.starfish.Person"); Person p1 = (Person) aClass.newInstance(); Constructor 的 newInstance(xxx),对构造器没有要求 Class aClass = Class.forName("priv.starfish.Person"); //获取构造器 Constructor

Java 并发高频面试题:聊聊你对 AQS 的理解?

安稳与你 提交于 2020-08-08 10:01:37
一、写在前面 这篇文章,我们来聊聊面试时一个比较有杀伤力的问题: 聊聊你对AQS的理解? 之前有同学反馈,去互联网公司面试,面试官聊到并发时就问到了这个问题。当时那位同学内心估计受到了一万点伤害。。。 因为首先,很多人可能连AQS是什么都不知道。或者仅仅是听说过AQS这个名词,但是可能连全称怎么拼写都不知道。 更有甚者,可能会说:AQS?是不是一种思想?我们平时开发怎么来用AQS? 总结起来,很多同学都对AQS有一种云里雾里的感觉,如果用搜索引擎查一下AQS是什么,估计看几篇文章就直接放弃了,因为密密麻麻的文字,实在是看不懂! 所以基于上述痛点,这篇文章就用最简单的大白话配合N多张手绘图,给大家讲清楚AQS到底是什么? 让各位同学面试被问到这个问题时,不至于不知所措。 二、ReentrantLock和AQS的关系 首先来看看,如果用java并发包下的ReentrantLock来加锁和释放锁,是个什么样的感觉? 这个学过java的同学应该都会吧,毕竟是java并发基本API的使用,我们直接看一下代码: 上面那段代码应该不难理解,无非就是搞一个Lock对象,然后加锁和释放锁。 你这时可能会问,这个跟AQS有啥关系? 关系大了去了!因为java并发包下很多API都是基于AQS来实现的加锁和释放锁等功能的,AQS是java并发包的基础类。 举个例子,比如说ReentrantLock

Java并发编程七 CAS自旋锁

拟墨画扇 提交于 2020-08-07 21:36:18
public class CASLockUtil { public static AtomicReference casLock = new AtomicReference<Thread>() ; /** * 加锁 * @param waitMillis 重试时间,如果超过这个时间则放弃当前的锁Millis * @return */ public static boolean lock ( long waitMillis){ long end = System. currentTimeMillis ()+waitMillis ; boolean isLock = casLock .compareAndSet( null, Thread. currentThread ()) ; while (!isLock&&end> System. currentTimeMillis ()){ isLock = casLock .compareAndSet( null, Thread. currentThread ()) ; } //如果是0就无限尝试 while (waitMillis== 0 &&!isLock){ isLock = casLock .compareAndSet( null, Thread. currentThread ()) ; } return isLock ; } /**

JVM 底层原理总结

梦想与她 提交于 2020-08-07 13:12:06
JAVA虚拟机: 一、如上图所示,JAVA虚拟机运行时主要由以下三个部分构成: A. 本地库接口 负责把描述类的数据从Class文件加载到内存,并对数据进行校验、装换解析、以及初始化,最终形成可以被虚拟机直接使用的Java类型。 在Java语言中,类型的加载、连接和初始化过程都是在程序运行期间完成的。 B. 运行时数据区 1)方法区。 2)堆。 3)虚拟机栈。 4)本地方法栈。 5)程序计数器。 C. 执行引擎 输入的是字节码文件,处理过程是字节码解析的过程,输出的是执行结果。 二、JVM生命周期: JVM实例对应了一个独立运行的Java程序,它是进程级别。 JVM执行引擎实例则对应了属于用户运行程序的线程,它是线程级别。 A. 启动: 启动一个Java程序时,一个JVM实例就产生了,任何一个拥有 public static void main(String[] args) 函数的class都可以作为JVM实例的运行起点。 B. 运行: main() 作为该程序初始线程的起点,任何其它线程均由该线程启动,JVM内部有两种线程(守护线程 和 非守护线程),main()属于非守护线程,守护线程通常由JVM自己使用,Java程序也可以标明自己创建的线程是守护线程。 C. 消亡: 当程序中的所有非守护线程终止时,JVM才退出,若安全管理器允许,程序也可以使用Runtime类或者System