2025.02.16笔记 ~ langhai

林书豪
2025-02-16 21:11:59
2025.02.16笔记 浪海值:47度
文章标签:java基础面试题
文章摘要:2025.02.16笔记
使用新的显示器:新的显示器 如果遇到图片单击即可放大/缩小。

synchronized 关键字原理👻 本文档纯手敲 可能存在错别字,本文档仅供学习使用。

Synchronized关键字作用就是 采用互斥的方式 在同一时刻 只能让一个线程持有 对象锁,其他线程想获取到这个 对象锁 就会阻塞。


底层实现 是 Monitor 也就是监视器的意思 c++语言实现 jvm提供

可以使用 javap命令进行反编译 查看字节码文件内容

字节码文件命令说明:

monitorenter  上锁

monitorexit 解锁

monitorexit 解锁

为什么会出现两遍解锁的操作?

类似 try catch finally 防止代码在出现异常的时候 没法释放对象锁

monitor的结构 由三部分组成

WaitSet wait方法 处于Waiting状态的线程

EntryList  其他线程要来竞争对象锁 就要在这里进行排队 也就是 Blocked 阻塞状态

Owner  也就是当前对象锁 被哪一个线程拥有 拥有者



Monitor 是重量级的锁 存在锁升级的过程

里面涉及 用户态和内核态的切换 进程上下文的切换 成本比较高 性能比较低

在多线程没有竞争的情况下 或者 基本没有竞争的情况下 直接加 重量级的锁 肯定不合适, JDK1.6 引入了两种锁来优化这一个问题 也就是 偏向锁和轻量级锁。


Monitor 怎么和 对象锁 关联上的呢

这里面就涉及 对象的内存结构  对象内存结构 构成之一 对象头

对象头里面 有一个 MarkWord 32bits

32bits的前提下:里面有两位 是 lock标识

重量级锁 30位 + 2位

30位 就是 指向对象监视器 Monitor 的指针  2位 10 表示 就是加的重量级锁。


轻量级锁 :当同步代码块当中 不存在竞争的时候,就是线程是交替执行的情况。

轻量级锁 30位 + 2位

30位 就是 指向栈中锁记录的指针 2位 00 表示 轻量级锁。


偏向锁:做进一步优化 一段很长的时间都只被一个线程使用锁

偏向锁 23位 + 2位 + 4位 + 1位 + 2位

23位就是持有偏向锁的线程ID thread, 2位就是偏向时间戳 epoch, 4位 对象分代年龄 age, 1位 就是偏向锁标识 biased_lock 1,   最后2位就是 01 标识锁标识。


当然 只要发生了锁的竞争 就会被升级为 重量级锁。



JVM

一次编写 到处运行

自动内存管理 垃圾回收机制


程序计数器 属于 运行数据区的一部分。

线程私有的 内部保存字节码的行号 记录正在执行的字节码指令的地址。


堆空间:线程共享的区域 主要用来保存 对象实例、数组等。

堆空间 里面分为 年轻代 (Eden S0 S1)老年代  java8之前还存在一个 永久代。


元空间 保存类信息、静态变量、常量、编译后的代码。


jdk8之后为什么要移除永久代,因为永久代大小是有限制的,如果类加载的过多,可能会导致永久代内存溢出,OutOfMemoryError,需要对虚拟机做出调优,就是jdk8之后的元空间区域,这个区域是存储在本地内存上面的。


栈空间:先进后出的特点,栈由栈帧(参数 局部变量表 返回地址)组成。

垃圾回收主要回收的是堆内存区域,栈帧在弹栈之后就会释放对应的内存。

方法内的局部变量是否线程安全?这个要分情况,局部变量如果引用了对象,逃离出方法的作用范围,可能会造成线程不安全的问题。

帧内存溢出情况:第一种栈帧过多,递归调用可能会出现这个问题。第二种就是栈帧的空间设置过大。


方法区:各个线程共享的内存区域,主要存储类的信息、运行时常量池。







四美java之父 浪海 本文档内容 请自行辨别


提交评论