当前位置: 首页 > news >正文

Java锁等待唤醒机制

在 Java 并发编程中,锁的等待和唤醒机制至关重要,通常使用 wait()notify()notifyAll() 来实现线程间的协调。本文将详细介绍这些方法的用法,并通过示例代码加以说明。

1. wait()notify()notifyAll()

在 Java 中,Object 类提供了 wait()notify()notifyAll() 方法,它们用于线程间的通信。

  • wait():使当前线程进入等待状态,并释放锁。
  • notify():唤醒单个等待线程。
  • notifyAll():唤醒所有等待线程。

注意,这些方法必须在同步代码块(synchronized)中调用,否则会抛出 IllegalMonitorStateException

2. 示例代码

下面的示例展示了 wait()notify() 的使用。

class SharedResource {
    private boolean available = false;
    
    public synchronized void produce() {
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        System.out.println("Producing an item");
        available = true;
        notify();
    }
    
    public synchronized void consume() {
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        System.out.println("Consuming an item");
        available = false;
        notify();
    }
}

public class WaitNotifyExample {
    public static void main(String[] args) {
        SharedResource resource = new SharedResource();
        
        Thread producer = new Thread(resource::produce);
        Thread consumer = new Thread(resource::consume);
        
        producer.start();
        consumer.start();
    }
}

3. wait()notify() 的工作原理

  1. 生产者线程 produce()availabletrue 时调用 wait() 进入等待状态,释放锁。
  2. 消费者线程 consume()availablefalse 时调用 wait() 进入等待状态,释放锁。
  3. produce() 生产后调用 notify() 唤醒 consume()
  4. consume() 消费后调用 notify() 唤醒 produce()

4. notifyAll() 的使用场景

notify() 仅唤醒一个线程,而 notifyAll() 可用于有多个等待线程的情况,以防止某些线程被永久阻塞。

public synchronized void produce() {
    while (available) {
        try {
            wait();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    System.out.println("Producing an item");
    available = true;
    notifyAll();
}

5. LockCondition 方式

除了 synchronized,还可以使用 LockCondition 进行等待和唤醒控制。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SharedResourceWithLock {
    private boolean available = false;
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    
    public void produce() {
        lock.lock();
        try {
            while (available) {
                condition.await();
            }
            System.out.println("Producing an item");
            available = true;
            condition.signal();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    
    public void consume() {
        lock.lock();
        try {
            while (!available) {
                condition.await();
            }
            System.out.println("Consuming an item");
            available = false;
            condition.signal();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
}

6. 总结

  • wait()notify() 需要在 synchronized 块中使用。
  • notifyAll() 可防止线程被永久阻塞。
  • LockCondition 提供更灵活的等待和唤醒机制。

合理使用这些机制可以提升 Java 多线程程序的性能和可靠性。

http://www.dtcms.com/a/84605.html

相关文章:

  • 【Linux】交叉编译2
  • 前端Wind CSS面试题及参考答案
  • 【数据分享】2014-2024年我国各城市逐年空气质量指数(AQI)数据
  • 设计心得——如何实现接口
  • 红宝书第十一讲:超易懂版「ES6类与继承」零基础教程:用现实例子+图解实现
  • 【transformer理论+实战(三)】必要的 Pytorch 知识
  • 在uml中,为什么用泛化而不用继承这个词语?
  • Python模块与包
  • 一、MySQL8的my.ini文件
  • linux ptrace 图文详解(三) PTRACE_ATTACH 跟踪程序
  • C语言入门教程100讲(8)算术运算符
  • Redis缓存与数据库 数据一致性保障
  • 2:认识数据库
  • 在 .NET 9.0 Web API 中实现 Scalar 接口文档及JWT集成
  • CIFAR10 数据集自定义处理方法
  • Spring Boot 整合 OpenFeign 教程
  • VitePress由 Vite 和 Vue 驱动的静态站点生成器
  • 自然语言处理(5)—— 中文分词
  • 高等数学-第七版-上册 选做记录 习题5-2
  • Linux——线程
  • 构音障碍(Dysarthria)研究全景总结(1996–2024)
  • 在Mac M1/M2芯片上完美安装DeepCTR库:避坑指南与实战验证
  • systemd-networkd 的 /etc/systemd/network/*.network 能不能一个文件配置多块网卡?不能
  • [01-04-02].第20节:PyQt5库初识及实现简易计算器
  • 网络安全基础
  • 文字变央视级语音转换工具
  • OpenRAND可重复的随机数生成库
  • 元宇宙时代下的 Facebook:机遇与挑战
  • IDEA修改默认作者名称
  • Android Compose 约束布局(ConstraintLayout、Modifier.constrainAs)源码深度剖析(十二)