java wait()notify释放锁

本文通过具体示例解释了Java中线程同步机制的核心概念,包括调用wait()方法如何释放锁以允许其他线程执行notify(),以及notify()何时释放锁。同时对比了yield()和sleep()方法在锁释放上的不同行为。

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

调用obj.wait()会立即释放锁,,以便其他线程可以执行obj.notify(),但是notify()不会立刻立刻释放sycronized(obj)中的obj锁,必须要等notify()所在线程执行完synchronized(obj)块中的所有代码才会释放这把锁.
//而 yield(),sleep()不会释放锁。
见如下代码:
public class WaitNotify {

	static boolean flag = true;
	static Object lock = new Object();

	public static void main(String[] args) throws Exception {
		Thread waitThread = new Thread(new Wait(), "WaitThread");
		waitThread.start();
		TimeUnit.SECONDS.sleep(1);
		Thread notifyThread = new Thread(new Notify(), "NotifyThread");
		notifyThread.start();
	}

	static class Wait implements Runnable {
		public void run() {
			// 加锁,拥有lock的Monitor
			synchronized (lock) {
				// 当条件不满足时,继续wait,同时释放了lock的锁
				while (flag) {
					try {
						System.out.println(Thread.currentThread()
								+ " flag is true. wait@ "
								+ new SimpleDateFormat("HH:mm:ss")
										.format(new Date()));
						lock.wait();
					} catch (InterruptedException e) {
					}
				}
				// 条件满足时,完成工作
				System.out.println(Thread.currentThread()
						+ " flag is false. running@ "
						+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
			}
		}
	}

	// wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify()
	// 但是notify()不会立刻立刻释放sycronized(obj)中的obj锁,必须要等notify()所在线程执行完synchronized(obj)块中的所有代码才会释放这把锁.
	// yield(),sleep()不会释放锁
	static class Notify implements Runnable {
		public void run() {
			// 加锁,拥有lock的Monitor
			synchronized (lock) {
				// 获取lock的锁,然后进行通知,通知时不会释放lock的锁,
				// 直到当前线程释放了lock后,WaitThread才能从wait方法中返回
				System.out.println(Thread.currentThread()
						+ " hold lock. notify @ "
						+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
				lock.notifyAll();
				flag = false;
				try {
					Thread.currentThread().sleep(5000l);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			// 再次加锁
			synchronized (lock) {
				System.out.println(Thread.currentThread()
						+ " hold lock again. sleep@ "
						+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
				try {
					Thread.currentThread().sleep(5000l);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

}
运行结果:
Thread[WaitThread,5,main] flag is true. wait@ 15:33:26
Thread[NotifyThread,5,main] hold lock. notify @ 15:33:27
Thread[NotifyThread,5,main] hold lock again. sleep@ 15:33:32
Thread[WaitThread,5,main] flag is false. running@ 15:33:37



<think>嗯,用户问的是Javanotify是否会释放。我需要回忆一下Java的线程机制。首先,waitnotify都是Object类的方法,必须在同步块或同步方法中使用。记得当线程调用wait()时,它会释放持有的,进入等待状态。那notify呢? 可能用户混淆了这两个方法的作用。比如,调用notify()的时候,线程是否立即释放?或者要等到同步块结束?我记得答案应该是后者,notify只是唤醒等待的线程,但自己会马上释放,得等到同步块执行完毕,或者遇到wait()才会释放。 比如,假设有一个synchronized块,里面调用了notify(),此时被唤醒的线程并能立即执行,必须等到当前线程退出同步块,释放之后。所以,notify本身释放释放的时机还是在同步代码块结束的时候。 过,可能需要更详细地解释这个过程,避免误解。比如,调用notify后,当前线程继续执行,直到退出synchronized块,这时候才会释放,被唤醒的线程才能去竞争。此外,如果有多个等待线程,notify只会随机唤醒一个,而notifyAll会唤醒所有,但它们都要等待可用。 另外,是否存在特殊情况?比如如果在调用notify之后,线程又调用了wait,这时候会释放,但这是另一个操作了。用户的问题集中在notify本身是否释放,应该回答释放,需要同步块结束或者显式释放。 应该举例说明,比如代码片段,展示notify在同步块中,然后其他线程必须等待当前线程释放。这样用户更容易理解。同时,需要强调正确使用waitnotify的范式,通常在循环中检查条件,避免虚假唤醒。 总结下来,notify释放释放的时机是同步块结束,或者线程主动调用wait()。这样用户就会混淆waitnotify的行为差异了。</think>在Java中,`notify()`方法的行为与释放的关系需要结合线程同步机制来理解。以下是分步说明: --- ### 1. **基础概念** - **`notify()`的作用**:唤醒一个正在`wait()`的线程(若有多个等待线程,随机唤醒一个)。 - **的持有者**:调用`notify()`的线程**必须已经持有**(即必须在`synchronized`代码块或方法中调用)。 --- ### 2. **`notify()`是否会释放?** **答案:会立即释放** - 调用`notify()`后,**当前线程会继续执行**,直到退出`synchronized`代码块或方法时,才会释放。 - **被唤醒的线程**:需要等待当前线程释放后,才能重新竞争。 --- ### 3. **示例代码说明 ```java synchronized (lock) { // 执行某些操作... lock.notify(); // 唤醒一个等待线程,但释放! // 当前线程继续执行其他操作... } // 此处退出synchronized块,释放 ``` - **关键时序**: 1. 线程A调用`lock.notify()`,唤醒线程B。 2. 线程B被唤醒,但需等待线程A退出`synchronized`块后,才能尝试获取。 3. 线程A执行完同步块后释放,线程B与其他线程竞争。 --- ### 4. **对比`wait()`的行为** - **`wait()`会释放**:调用`wait()`后,线程立即释放并进入等待状态。 - **`notify()`释放**:只有同步块自然结束或显式调用`wait()`时才会释放。 --- ### 5. **注意事项** - **典型使用模式**:`wait()`和`notify()`通常与条件检查配合使用,避免虚假唤醒: ```java synchronized (lock) { while (condition满足) { lock.wait(); // 释放并等待 } // 执行操作后唤醒其他线程 lock.notify(); } ``` - **的公平性**:被唤醒的线程需与其他活跃线程竞争保证立即执行。 --- ### 总结 - **`notify()`释放**,它仅通知等待线程可以竞争。 - **释放的时机**:在调用线程退出`synchronized`块或主动调用`wait()`时。 - **设计建议**:始终通过循环检查条件变量,确保线程安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值