在Java中,wait、notify
方法通常与synchronized
关键字一起使用,这样做有几个重要的原因,主要涉及线程的协调和正确的并发控制。以下是一些关键点:
-
监视器锁(Monitor Lock):
- 每个对象在Java中都可以作为一个监视器锁,用来管理对该对象的同步访问。当一个线程持有一个对象的监视器锁时,其他线程无法同时获取这个锁。
wait
方法必须在持有监视器锁的情况下调用,也就是说,wait
方法必须在synchronized
块或synchronized
方法中调用。调用wait
方法的线程会放弃该对象的监视器锁,同时进入等待状态,直到另一个线程调用同一对象上的notify
或notifyAll
方法。
-
释放锁和等待:
- 当一个线程调用对象的
wait
方法时,它会释放该对象的监视器锁,并等待被唤醒。如果没有synchronized
关键字保证线程在调用wait
方法时已经持有锁,就无法确保线程在进入等待状态前不会与其他线程发生竞争条件(race condition)。 - 只有持有监视器锁的线程才能调用
wait
方法,这样可以确保在进入等待状态之前不会有其他线程修改共享资源,从而避免不一致的状态。
- 当一个线程调用对象的
-
线程协调:
wait
、notify
和notifyAll
方法提供了一种线程间通信的机制,使得一个线程可以通过这些方法来通知其他线程某些条件已经满足。synchronized
关键字确保了只有一个线程能够在某个时间段内执行持有相同监视器锁的代码,从而避免多个线程同时修改共享资源导致的数据不一致问题。
简而言之,wait
方法需要与synchronized
一起使用,以确保线程在进入等待状态之前,已经安全地获取了监视器锁,并且在被唤醒后能够重新获得锁。这种机制确保了线程间的协调和共享资源的一致性。
举个简单的例子说明:
class SharedResource {
private boolean condition = false;
public synchronized void waitForCondition() throws InterruptedException {
while (!condition) {
wait();
}
// do something after condition is true
}
public synchronized void changeCondition() {
condition = true;
notify(); // or notifyAll();
}
}
在这个例子中,waitForCondition
方法使用synchronized
关键字来获取锁,然后调用wait
方法。当changeCondition
方法改变条件并调用notify
或notifyAll
方法时,等待的线程将被唤醒并继续执行,同时它们会重新获取锁。
再写一段代码
/**
* 功能描述: Java多线程中的 wait() 和 notify() 方法
* @author Songxianyang
* @date 2024-06-25 17:38
*/
public class WaitNotify {
public void waitTest(Object lock) throws InterruptedException {
synchronized (lock) {
lock.wait();
System.out.println("线程等待!!!释放锁等待----"+Thread.currentThread().getName());
}
}
@SneakyThrows
private void notifyTest(Object lock) {
synchronized (lock) {
// lock.notify();
lock.notifyAll();
System.out.println("唤醒线程呀哈哈哈---(唤醒其中一个线程,去枪锁)"+Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(2);
}
}
public static void main(String[] args) {
Object lock = new Object();
Thread thread = new Thread(()->{
WaitNotify waitNotify = new WaitNotify();
try {
waitNotify.waitTest(lock);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"线程1");
thread.start();
Thread thread2 = new Thread(()->{
WaitNotify waitNotify = new WaitNotify();
try {
waitNotify.waitTest(lock);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"线程2");
thread2.start();
Thread thread3 = new Thread(()->{
WaitNotify waitNotify = new WaitNotify();
waitNotify.notifyTest(lock);
},"线程3");
thread3.start();
}
}
上面得例子可得:
-
方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。
-
如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 “先来后到”)
-
在notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 深入理解Java多线程中的 wait() 和 notify():为何要与 synchronized 手牵手
发表评论 取消回复