Java如何加监视器?

在Java中通过synchronized关键字实现监视器机制,对共享资源加锁确保线程安全,具体方式:,1. 同步代码块:synchronized(obj){…},2. 同步方法:public synchronized void method(){…},3. 配合wait()/notify()实现线程间通信

在Java中,监视器(Monitor)是一种同步机制,用于控制多线程环境下对共享资源的访问,它通过内置锁(synchronized)和线程通信方法(wait(), notify(), notifyAll())实现线程安全,以下是详细实现方法:

Java如何加监视器?


监视器的核心:synchronized 关键字

Java 中每个对象都有一个内置锁(Monitor Lock),通过 synchronized 关键字触发:

  1. 同步代码块
    锁定指定对象:

    public void safeMethod() {
        synchronized (lockObject) { // lockObject 是任意对象
            // 临界区代码(共享资源操作)
        }
    }
  2. 同步方法
    锁定当前实例(this)或类(静态方法):

    Java如何加监视器?

    public synchronized void safeMethod() { 
        // 操作共享资源 
    }
    public static synchronized void staticSafeMethod() { 
        // 静态方法锁定 Class 对象 
    }

线程通信:wait() 与 notify()

监视器通过 wait()notify() 实现线程间协作:

  1. wait()
    释放锁并让线程进入等待状态(需在 synchronized 块内调用):

    synchronized (lockObject) {
        while (条件不满足) {
            lockObject.wait(); // 释放锁,线程等待
        }
        // 条件满足后继续执行
    }
  2. notify() / notifyAll()
    唤醒等待线程(notify() 随机唤醒一个,notifyAll() 唤醒所有):

    synchronized (lockObject) {
        // 改变条件
        lockObject.notify(); // 唤醒一个等待线程
        // 或 lockObject.notifyAll();
    }

完整示例:生产者-消费者模型

import java.util.LinkedList;
import java.util.Queue;
public class MonitorExample {
    private final Queue<Integer> queue = new LinkedList<>();
    private final int CAPACITY = 5;
    private final Object lock = new Object(); // 监视器锁对象
    // 生产者
    public void produce(int item) throws InterruptedException {
        synchronized (lock) {
            while (queue.size() == CAPACITY) {
                lock.wait(); // 队列满时等待
            }
            queue.add(item);
            System.out.println("生产: " + item);
            lock.notifyAll(); // 唤醒消费者
        }
    }
    // 消费者
    public void consume() throws InterruptedException {
        synchronized (lock) {
            while (queue.isEmpty()) {
                lock.wait(); // 队列空时等待
            }
            int item = queue.poll();
            System.out.println("消费: " + item);
            lock.notifyAll(); // 唤醒生产者
        }
    }
}

关键注意事项

  1. 避免死锁
    • 确保锁的获取顺序一致。
    • 使用超时机制:wait(long timeout)
  2. 使用 while 而非 if 检查条件
    防止虚假唤醒(Spurious Wakeup),重复检查条件。
  3. 优先用 notifyAll()
    notify() 可能因唤醒错误线程导致死锁。
  4. 锁粒度优化
    减小同步代码块范围,提升性能(如避免在 synchronized 内执行耗时操作)。
  5. 替代方案
    复杂场景推荐 java.util.concurrent 包(如 ReentrantLockCondition)。

监视器的工作原理

  1. 当线程进入 synchronized 块时,获取对象的监视器锁。
  2. 若锁已被占用,线程进入阻塞队列(Entry Set) 等待。
  3. 线程调用 wait() 后,释放锁并进入等待队列(Wait Set)
  4. 其他线程调用 notify() 时,等待队列中的线程移至阻塞队列,重新竞争锁。

Java 的监视器机制通过 synchronized + wait()/notify() 实现线程同步与协作,正确使用时需注意:

  • 锁范围最小化以提升性能。
  • while 循环检查条件,避免虚假唤醒。
  • 高并发场景优先使用 java.util.concurrent 工具类(如 BlockingQueue)。

引用说明基于 Oracle 官方文档 Java Concurrency 和 Brian Goetz 所著《Java Concurrency in Practice》,实践代码遵循线程安全最佳实践,适用于 JDK 8 及以上版本。

Java如何加监视器?

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/45993.html

(0)
酷盾叔的头像酷盾叔
上一篇 2025年7月4日 23:30
下一篇 2025年7月4日 23:40

相关推荐

  • 如何升级32位Java到64位

    确认当前版本后卸载32位Java,从官网下载64位JDK/JRE安装包,安装时选择自定义路径避免冲突,最后更新JAVA_HOME和Path环境变量指向新版本。

    2025年6月8日
    000
  • Java如何处理斜杠字符串?

    在Java中处理斜杠字符串需注意转义:反斜杠\是转义字符,需双写\\表示字面量;正斜杠/可直接使用,路径处理推荐Paths.get()或File.separator保证跨平台兼容性,正则表达式需双重转义。

    2025年6月18日
    100
  • Java如何快速导入库?

    在Java项目中导入外部库主要有三种方式:使用IDE(如IntelliJ/Eclipse)自动添加依赖;手动下载JAR文件并加入项目构建路径;或通过构建工具(如Maven/Gradle)在配置文件中声明依赖后自动下载管理,推荐使用Maven/Gradle简化流程。

    2025年6月11日
    200
  • Java汉字如何比较大小?

    在Java中比较汉字大小,可直接使用String.compareTo()方法按Unicode编码值比较,或通过Collator类按中文排序规则(如拼音)比较。 ,1. “字”.compareTo(“符”) 返回Unicode差值 ,2. Collator.getInstance(Locale.CHINA).compare(“汉”, “字”) 按拼音顺序比较

    2025年6月7日
    100
  • Java如何实现文件上传下载?

    在Java中实现文件上传通常使用Servlet的Part接口或第三方库如Apache Commons FileUpload处理HTTP请求流;下载文件则通过设置响应头Content-Disposition并读取文件流写入响应输出流完成,核心步骤包括解析请求、读写文件流和异常处理。

    2025年6月11日
    100

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN