【Java线程和synchronized锁】
摘要:本文系统介绍了Java线程同步机制和线程状态。synchronized锁通过Monitor管程实现,包含轻量级锁、锁膨胀和偏向锁等优化机制,详细阐述了加锁、锁竞争和锁升级过程。同时解析了wait方法的工作原理及其与sleep的区别。最后全面梳理了线程的七大状态(新建、就绪、运行、阻塞、等待、超时等待和终止)及其转换条件,完整呈现了线程的生命周期。全文从底层原理到应用场景,系统性地讲解了Jav
摘要:
本文系统介绍了Java线程同步机制和线程状态。synchronized锁通过Monitor管程实现,包含轻量级锁、锁膨胀和偏向锁等优化机制,详细阐述了加锁、锁竞争和锁升级过程。同时解析了wait方法的工作原理及其与sleep的区别。
最后全面梳理了线程的七大状态(新建、就绪、运行、阻塞、等待、超时等待和终止)及其转换条件,完整呈现了线程的生命周期。全文从底层原理到应用场景,系统性地讲解了Java线程同步与状态管理的核心知识。
一,synchronized锁原理
1,工作原理
synchronized锁的对象会关联到一个Monitor(管程),该线程会占有这个Monitor的Owner属性,代表该线程拿到锁;若其他线程执行synchronized(同一对象)会根据锁对象找到管程,Owner不为null,所以会上下文切换到阻塞态并加入到队列中。

2,轻量级锁
(1)对一个对象加锁时,首先会在该线程函数调用的栈帧内创造一个锁记录,包含锁记录地址、锁标记(轻量级00,重量级10)和对象引用
(2)加锁时,交换锁记录的地址及标记行与对象的mark word,表示该对象已被加锁
(3)当该线程内其他方法调用再次对这个对象加锁(无锁竞争),检查对象头的mark word行发现标记为00代表已被上锁,通过锁记录引用找到记录为同一个线程内,进行锁重入,记录行为null,对象引用指向该对象。

3,锁膨胀
(1)当其他线程对该对象上锁(锁竞争),上锁必定失败,此时会发生锁膨胀
(2)该对象会被分配一个管程对象Monitor,mark word记录管程地址且标记变为10,Owner置为该对象引用,竞争线程阻塞并被放入EntryList中等待被唤醒
(3)自旋优化(多核):当其他线程进行锁竞争失败时不会直接阻塞而是进行自旋重试,继续尝试获取锁;如果一段时间自旋都失败才会进入阻塞状态。

4,偏向锁
开启偏向锁,markword的最后三位为101,其存储内容也会发生变化-->ThreadID和epoch
(1)调用偏向对象的hashcode时,会撤销偏向锁到不可偏向状态
(2)其他线程交错地对该对象上锁,偏向锁会升级到轻量级锁,解锁后会撤销到不可偏向状态
批量重偏向优化:当撤销偏向次数达到阈值20后,不再撤销偏向(损耗性能),而是批量地将线程id替换为另一个偏向的线程
二,wait基本原理
wait是Object类的固有方法,调用时会使当前线程进入WaitSet集合中等待,常用于线程因为缺少某个条件暂时解锁等待的场景。
1,工作原理

2,Wait和Sleep的区别
(1)sleep是Thread方法,wait是Object方法
(2)sleep不需要和synchronized配合使用,但wait需要和synchronized一起使用
(3)sleep在上锁时调用时不会释放锁对象,而wait在等待时会释放对象锁
(4)sleep和wait时线程的状态都是Timed_Waiting
三,线程的七大状态
1. 新建状态(New)
(1)定义:当线程对象被创建(如 new Thread())但尚未调用 start() 方法时,线程处于新建状态。
(2)特点:此时线程尚未进入 JVM 的线程调度器,不占用 CPU 资源,仅存在于内存中。
(3)转换:调用 start() 方法后,线程进入就绪状态。
2. 就绪状态(Runnable)
(1)定义:线程调用 start() 方法后进入就绪状态(也称为 “可运行状态”)。此外,线程从阻塞状态或等待状态恢复后,也会先进入就绪状态。
(2)特点:线程已被 JVM 线程调度器管理,具备运行条件,但尚未获得 CPU 使用权(等待操作系统调度)。
(3)转换:当操作系统调度该线程时,线程进入运行状态。
3. 运行状态(Running)
(1)定义:线程获得 CPU 执行权,正在执行 run() 方法中的代码。
(2)特点:同一时刻,一个 CPU 核心只能运行一个线程(多核心 CPU 可并行运行多个线程)。
(3)转换:若线程的时间片用完或被更高优先级线程抢占,线程回到就绪状态。若线程执行了 sleep()、wait() 等方法,或尝试获取同步锁失败,进入等待状态 / 阻塞。若 run() 方法执行完毕或抛出未捕获异常,线程进入终止状态。
4. 阻塞状态(Blocked)
(1)定义:线程因等待获取同步锁(如进入 synchronized 代码块但未获得锁)而暂时停止运行。
(2)特点:线程不占用 CPU 资源,等待其他线程释放锁后才能继续竞争 CPU 执行权。
(3)转换:当线程成功获取同步锁后,进入就绪状态。
5. 等待状态(Waiting)
(1)定义:线程因调用无超时参数的等待方法而进入无限期等待状态,需被其他线程显式唤醒才能继续运行(wait()、sleep()、park()等)。
(2)特点:线程不占用 CPU 资源,且不会自动唤醒,必须依赖其他线程的操作。
(3)转换:被其他线程唤醒后,线程进入就绪状态。
6. 超时等待状态(Timed Waiting)
(1)定义:线程因调用带超时参数的等待方法而进入有限期等待状态,超时后会自动唤醒,或可被其他线程提前唤(sleep(long millis)、wait(long timeout)、parkNanos(long nanos)等)。
(2)特点:线程不占用 CPU 资源,但等待时间是有限的,无需其他线程唤醒也能自动恢复。
(3)转换:超时后或被提前唤醒后,线程进入就绪状态。
7. 终止状态(Terminated)
(1)定义:线程的 run() 方法执行完毕,或因未捕获异常导致线程终止,进入终止状态。
(2)特点:线程生命周期结束,无法再被调度或恢复到其他状态(即使调用 start() 方法也会抛出 IllegalThreadStateException)。
(3)触发原因:正常终止:run() 方法执行完成。异常终止:线程执行过程中抛出未捕获的异常(如 RuntimeException)。
更多推荐

所有评论(0)