Java多线程同步方法wait与notify/notifyAll机制实现方式

一、基本机制与使用条件

  1. 方法定义与作用

    • wait():当前线程释放锁并进入等待池(Wait Set),等待被其他线程唤醒。
    • notify():唤醒等待池中一个随机线程,使其进入锁池(Lock Queue),重新竞争锁。
    • notifyAll():唤醒等待池中所有线程,均进入锁池竞争锁。
  2. 使用要求

    • 必须在同步代码块或方法中调用,否则抛出IllegalMonitorStateException
    • 调用者必须是当前同步块的锁持有者(即对象的监视器)。

二、实现流程与线程状态转换

  1. 线程调用wait()的流程

    • 线程执行wait()后,释放锁,进入等待池。
    • 线程状态从RUNNABLE变为WAITING(或TIMED_WAITING,若调用带超时的wait(long))。
    • 其他线程调用notify()notifyAll()后,等待池中的线程被唤醒,进入锁池,等待重新获取锁。
  2. 唤醒与锁竞争

    • 唤醒的线程需重新通过同步锁的竞争机制(如CAS操作)获取锁,成功后进入RUNNABLE状态继续执行。
    • 若锁竞争失败,线程可能再次进入锁池等待。

三、关键注意事项与最佳实践

  1. 循环条件检查

    • 避免虚假唤醒:wait()可能因系统中断或非预期事件被唤醒,需在循环中检查条件,而非单次判断。
      synchronized (lock) {
          while (conditionNotMet) {
              lock.wait();  // 循环检查条件
          }
          // 执行后续操作
      }
      
  2. 优先使用notifyAll()

    • notify()可能仅唤醒一个线程,若该线程无法满足后续条件(如生产者线程被唤醒但队列未空),可能导致其他线程饥饿。
    • notifyAll()确保所有等待线程重新竞争锁,避免遗漏唤醒。
  3. 异常处理

    • wait()可能抛出InterruptedException,需在try-catch块中处理,避免线程意外终止。

四、典型应用场景

  1. 生产者-消费者模型

    • 生产者:在队列满时调用wait(),队列有空间时notifyAll()唤醒消费者。
    • 消费者:在队列空时调用wait(),队列有数据时notifyAll()唤醒生产者。
    • 代码示例(基于文章1):
      public synchronized void produce(T item) throws InterruptedException {
          while (queue.size() == maxSize) {  // 循环检查条件
              wait();
          }
          queue.add(item);
          notifyAll();  // 唤醒所有等待线程
      }
      
  2. 交替打印数字

    • 线程协作:一个线程打印奇数,另一个打印偶数,通过notify()交替唤醒。
    • 代码示例(基于文章9):
      public void run() {
          synchronized (this) {
              notify();  // 唤醒另一个线程
              while (i <= 100) {
                  System.out.println[i++]);
                  try {
                      wait();  // 当前线程等待
                  } catch (InterruptedException e) { ... }
              }
          }
      }
      

五、与synchronized的协同作用

  • 锁的释放与重新获取:wait()释放锁后,其他线程可进入同步块修改共享资源;唤醒后需重新获取锁才能继续执行。
  • 条件变量:通过wait()notify()实现多条件协作,而synchronized仅提供基础的互斥机制。

六、总结

wait()notify()notifyAll()通过锁机制实现线程间的高效协作,其核心在于条件检查、锁释放与唤醒的协同。开发者需注意循环检查条件、优先使用notifyAll(),并结合synchronized确保线程安全。正确应用这些方法可解决生产者-消费者、任务调度等复杂场景的同步问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DKPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值