Java线程状态与线程通讯wait/notify,park/unpark机制

本文详细介绍了Java线程的6种状态,包括NEW、Runnable、Blocked、Waiting、Timed Waiting和Terminated。重点讨论了线程间通信,特别是wait/notify、park/unpark机制的使用,以及它们与suspend/resume、wait/notify、stop/destroy/interrupt的区别。线程通信中的伪唤醒问题和循环检查等待条件的必要性也被提及。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java线程状态

Java线程共有6个状态,在java.lang.Thread.State中明确定义。

线程状态图:

1.NEW  尚未启动的线程的状态

2.Runnable  可运行的线程的状态,包括等待CPU调度和正在运行的线程的状态

3.Blocked  等待监视器锁的阻塞线程的状态,处于synchronized同步代码块或方法中被阻塞

4.Waiting  等待线程的状态。通过下列不带超时的方式:Object.wait、Thread.join、LockSupport.park

处于等待状态的线程正在等待另一个线程执行特定的动作,如一个线程调用了Object.wait(),此时会等待另一个线程调用同一个对象的Object.notify()或Object.notifyAll()

5.Timed Waiting  指定等待时间的等待线程的状态,通过下列带超时的方式:

Thread.sleep、Object.wait、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil

6.Terminated  终止线程的状态。线程正常执行完成或出现异常而终止

 

线程间通信

要想实现多个线程之间的协同,如:线程执行先后顺序、获取某个线程执行的结果,终止某个线程等,涉及到线程之间的相互通讯,分为下面四类:

  1. 文件共享
  2. 网络共享
  3. 共享变量
  4. jdk提供的线程协调API

这里主要讲通过JDK提供的API实现线程间的协作,JDK中对于需要多线程协作完成某一

<think>好的,用户想了解Java中Object类的waitnotify方法的底层实现机制,包括调用链和JVM源码分析。我需要结合提供的引用内容,整理出一个清晰的回答。 首先,根据引用1,waitnotify是Object类的方法,每个Java对象都有。接着引用3提到,在JVM源码中,notifynotifyAll不会立即释放ObjectMonitor,而是在执行monitorexit指令时才释放。引用4和5指出底层使用了park/unpark机制,在Linux下通过pthread_cond实现,线程wait时会放弃CPU。引用5还提到了ObjectMonitor的exit方法。 需要分步骤解释:首先,Java层的方法调用如何进入JVM,然后JVM如何处理,涉及ObjectMonitor对象,以及线程状态的变化。还要说明锁的释放时机,可能存在的竞争问题,比如为什么要在同步块中使用这些方法。引用2中的代码示例展示了同步块的使用,但用户可能想知道底层如何保证同步。 需要组织信息,从Java API到JVM源码,再到操作系统层的实现。可能的结构是:Java层调用 -> JVM入口 -> ObjectMonitor机制 -> 线程挂起唤醒 -> 系统调用。同时要结合引用中的各个点,比如park/unpark和pthread_cond的关系,以及monitorexit的重要性。 还需要注意用户可能对性能感兴趣,如引用4提到的线程放弃CPU,这对系统性能的影响。此外,引用3和5提到的entry set和ObjectWaiter节点,可以解释线程如何被管理。 最后生成相关问题时,要涵盖底层机制、使用注意事项、性能影响和其他线程工具的比较。</think>### Java Object类wait/notify方法底层实现机制 #### 1. 核心调用链路 Java层调用 `wait()`/`notify()` 方法时,会通过以下路径进入JVM实现: ``` Java API -> JVM_ENTRY(jvm.cpp) -> ObjectMonitor::wait()/notify() ``` 具体过程: - **Java层调用**:`synchronized(obj) { obj.wait(); }` 触发`monitorenter`指令 - **JVM入口**:`jvm.cpp`中的`JVM_MonitorWait`和`JVM_MonitorNotify`方法 - **对象监视器**:通过`ObjectMonitor`对象管理线程状态(每个Java对象关联一个ObjectMonitor)[^3][^5] #### 2. ObjectMonitor关键结构 ```cpp class ObjectMonitor { volatile markOop _header; // 对象头 void* volatile _owner; // 持有锁的线程 ObjectWaiter* _WaitSet; // 等待队列(wait线程) ObjectWaiter* _EntryList; // 阻塞队列(等待锁的线程) // ... } ``` - `_WaitSet`存储处于WAITING状态线程(通过wait()进入) - `_EntryList`存储等待获取锁的BLOCKED线程 #### 3. wait()实现步骤 ```cpp void ObjectMonitor::wait(jlong millis, bool interruptible) { // 1. 构造ObjectWaiter节点 ObjectWaiter node(Self); // 2. 将线程加入_WaitSet队列 AddWaiter(&node); // 3. 释放锁并触发monitorexit exit(true, Self); // 4. 调用park挂起线程(底层通过pthread_cond_wait实现) park(millis); // 5. 被唤醒后重新竞争锁 enter(Self); } ``` 关键点: - 调用`wait()`会立即释放对象锁(通过`exit()`触发monitorexit) - 线程挂起通过操作系统级条件变量实现(Linux下`pthread_cond_wait`)[^4] #### 4. notify()实现步骤 ```cpp void ObjectMonitor::notify(TRAPS) { // 1. 从_WaitSet移出第一个等待线程 ObjectWaiter* iterator = DequeueWaiter(); // 2. 将线程转移到_EntryList或直接唤醒 if (Policy == 0) { // 默认策略:移入EntryList enqueue(iterator); } else { // 策略1:直接唤醒 unpark(iterator->_thread); } } ``` 重要特性: - `notify()`不会立即释放锁,实际锁释放发生在同步块结束的`monitorexit`指令 - 被唤醒的线程需要重新竞争锁才能继续执行[^5] #### 5. 操作系统层实现 - **挂起**:通过`pthread_cond_wait()`让出CPU,线程进入WAITING状态 - **唤醒**:`pthread_cond_signal()`触发线程调度 - **性能优势**:挂起的线程不占用CPU时间片[^4] #### 6. 典型问题案例 引用[2]中的代码存在严重问题: ```java synchronized (flag) { flag = "false"; // 修改锁对象引用导致后续notify失效 flag.notify(); } ``` 当修改`flag`引用后,其他线程的`synchronized(flag)`可能锁定不同对象,导致`notify()`失效。这是典型的对象锁引用逃逸问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值