Java的对象监视器

简介: 摘要:Java中的监视器(Monitor)是线程同步机制,每个对象带有一个与之关联的监视器。线程通过`synchronized`获取和释放锁。监视器包含入口集(等待锁的线程)、所有者线程(持锁线程)和等待集(调用`wait()`的线程)。线程在入口集阻塞,等待集调用`wait()`后释放锁进入等待。线程状态包括新建、可运行、阻塞、等待、超时等待和终止。示例代码展示了线程如何在不同状态间转换,如线程获取和释放监视器锁以及调用`wait()`和`notify()`方法。

什么是监视器(Monitor)?

在Java中,监视器(Monitor)是用来实现线程同步的一种机制。每个Java对象都有一个与之关联的监视器,线程可以通过synchronized关键字来获取和释放对象的监视器。监视器的主要作用是确保在同一时刻只有一个线程可以执行同步块或同步方法,从而实现线程的互斥访问。

监视器的组成部分

监视器通常包含以下三个关键部分:

  1. 入口集(Entry Set):等待获取监视器锁的线程集合。
  2. 所有者线程(Owner Thread):当前持有监视器锁的线程。
  3. 等待集(Wait Set):调用了wait()方法并进入等待状态的线程集合。

线程等待的地方

  • 入口集(Entry Set):线程在尝试进入同步块或同步方法时,如果无法获取监视器锁,它们会进入入口集等待。这些线程处于阻塞状态,等待获取监视器锁。
  • 等待集(Wait Set):线程在调用wait()方法后,会释放监视器锁并进入等待集。这些线程处于等待状态,直到被其他线程通过notify()notifyAll()方法唤醒。

线程状态转换示意图

以下是线程在不同状态之间转换的过程示意图:

  1. 新建状态(New):线程被创建,但尚未启动。
  2. 可运行状态(Runnable):线程已经启动,可以运行但不一定正在运行。
  3. 阻塞状态(Blocked):线程在入口集中,等待获取监视器锁。
  4. 等待状态(Waiting):线程在等待集中,等待其他线程通过notify()notifyAll()唤醒。
  5. 超时等待状态(Timed Waiting):线程在等待集中,等待特定时间后被唤醒。
  6. 终止状态(Terminated):线程已经结束执行。

示例代码解释

我们通过一个示例代码来解释线程在不同状态之间的转换:

public class MonitorExample {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock) {
try {
                    System.out.println("Thread 1: Acquired lock, entering wait state.");
                    lock.wait();
                    System.out.println("Thread 1: Woken up, reacquired lock.");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
Thread thread2 = new Thread(() -> {
synchronized (lock) {
                System.out.println("Thread 2: Acquired lock, notifying.");
                lock.notify();
                System.out.println("Thread 2: Notified, releasing lock.");
            }
        });
        thread1.start();
try {
            Thread.sleep(100); // Ensure thread1 starts first and enters wait state
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        thread2.start();
    }
}

过程解释

  1. Thread 1 获取监视器锁
  • Thread 1 进入同步块并获取监视器锁。
  • 调用lock.wait()方法,Thread 1释放监视器锁并进入等待集。
  1. Thread 2 获取监视器锁
  • Thread 2 进入同步块并获取监视器锁(此时Thread 1已在等待集)。
  • 调用lock.notify()方法,唤醒等待集中的一个线程(即Thread 1)。
  1. Thread 2 释放监视器锁
  • Thread 2 退出同步块,释放监视器锁。
  1. Thread 1 重新获取监视器锁
  • 被唤醒的Thread 1从等待集中移动到锁池,重新竞争获取监视器锁。
  • Thread 1成功获取监视器锁后,从wait()方法返回,继续执行后续代码。

总结

  • 监视器(Monitor):用于实现线程同步,每个Java对象都有一个监视器。
  • 入口集(Entry Set):线程在尝试进入同步块或同步方法时,如果无法获取监视器锁,会进入入口集等待。
  • 等待集(Wait Set):线程在调用wait()方法后,会释放监视器锁并进入等待集,等待被唤醒。
  • 状态转换:线程在不同状态之间转换,包括新建、可运行、阻塞、等待、超时等待和终止状态。
相关文章
|
1月前
|
存储 缓存 监控
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
33 0
|
4天前
|
缓存 前端开发 Java
【前端学java】复习巩固-Java中的对象比较(15)
【8月更文挑战第11天】Java中的对象比较
14 1
【前端学java】复习巩固-Java中的对象比较(15)
|
11天前
|
存储 Java 程序员
Java中对象几种类型的内存分配(JVM对象储存机制)
Java中对象几种类型的内存分配(JVM对象储存机制)
45 5
Java中对象几种类型的内存分配(JVM对象储存机制)
|
3天前
|
Java API 开发者
|
11天前
|
存储 Java 程序员
08 Java面向对象基础(对象与类+实例变量与方法+构造方法+this关键字)
08 Java面向对象基础(对象与类+实例变量与方法+构造方法+this关键字)
33 4
|
15天前
|
存储 安全 Java
揭秘Java序列化神器Serializable:一键解锁对象穿越时空的超能力,你的数据旅行不再受限,震撼登场!
【8月更文挑战第4天】Serializable是Java中的魔术钥匙,开启对象穿越时空的能力。作为序列化的核心,它让复杂对象的复制与传输变得简单。通过实现此接口,对象能被序列化成字节流,实现本地存储或网络传输,再通过反序列化恢复原状。尽管使用方便,但序列化过程耗时且存在安全风险,需谨慎使用。
27 7
|
2天前
|
存储 设计模式 Java
在 Java 中创建多个对象
【8月更文挑战第17天】
6 0
|
5天前
|
Java Spring 容器
Java SpringBoot 中,动态执行 bean 对象中的方法
Java SpringBoot 中,动态执行 bean 对象中的方法
14 0
|
5天前
|
Java
Java Bean 注册对象
Java Bean 注册对象
6 0
|
27天前
|
Java 运维
开发与运维技术问题之ava对象头压缩技术支持所有的Java垃圾回收器如何解决
开发与运维技术问题之ava对象头压缩技术支持所有的Java垃圾回收器如何解决
21 1