在Java中,wait、notify方法通常与synchronized关键字一起使用,这样做有几个重要的原因,主要涉及线程的协调和正确的并发控制。以下是一些关键点:

  1. 监视器锁(Monitor Lock)

    • 每个对象在Java中都可以作为一个监视器锁,用来管理对该对象的同步访问。当一个线程持有一个对象的监视器锁时,其他线程无法同时获取这个锁。
    • wait方法必须在持有监视器锁的情况下调用,也就是说,wait方法必须在synchronized块或synchronized方法中调用。调用wait方法的线程会放弃该对象的监视器锁,同时进入等待状态,直到另一个线程调用同一对象上的notifynotifyAll方法。
  2. 释放锁和等待

    • 当一个线程调用对象的wait方法时,它会释放该对象的监视器锁,并等待被唤醒。如果没有synchronized关键字保证线程在调用wait方法时已经持有锁,就无法确保线程在进入等待状态前不会与其他线程发生竞争条件(race condition)。
    • 只有持有监视器锁的线程才能调用wait方法,这样可以确保在进入等待状态之前不会有其他线程修改共享资源,从而避免不一致的状态。
  3. 线程协调

    • waitnotifynotifyAll方法提供了一种线程间通信的机制,使得一个线程可以通过这些方法来通知其他线程某些条件已经满足。
    • 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方法改变条件并调用notifynotifyAll方法时,等待的线程将被唤醒并继续执行,同时它们会重新获取锁。

再写一段代码

/**
 * 功能描述:  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()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部