开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
在Java编程语言中,Java中的每个对象都与一个监视器相关联,线程可以锁定或解锁该监视器。
每个对象除了具有关联的监视器外,还具有关联的等待集。当一个对象第一次创建时,它的等待集为空。向等待集中添加线程和从等待集中删除线程的基本操作是原子的。等待集仅通过Object方法进行操作。等,对象。notify(通知动作)和Object。notifyAll(通知)。
一次只能有一个线程持有监视器上的锁(即在任何时候只有一个线程可以进入关键区域,这是由Java Scheduler基于某些标准(例如FIFO)决定的)。任何其他试图锁定该监视器的线程都将被阻塞,直到它们能够获得该监视器上的锁(即剩余的线程在监视器的wait Set块中等待)。如果当前线程由于某种原因被挂起,那么线程将被移回等待设置区域,然后重新调度以获得临界区域)。
每个Java对象都包含锁信息。
如果任何线程想访问该对象的实例变量;然后线程必须“拥有”对象的锁(在锁内存区设置一些标志)。这是保存与锁相关信息的关键区域或锁内存区域。
现在,在简要了解Java对象监视器之后,让我们访问监视器和锁的定义:
什么是监视器?根据维基百科
在并发编程中,监视器是一种同步构造,它允许线程具有互斥和等待(阻塞)某个条件变为false的能力。监视器还有一种机制,可以向其他线程发出信号,告诉它们的条件已经满足。监视器由互斥(锁)对象和条件变量组成。条件变量本质上是等待特定条件的线程的容器。监控器为线程提供了一种机制,可以暂时放弃独占访问,以便在重新获得独占访问并恢复任务之前等待满足某些条件。
什么是锁?来自锁和同步的官方文档(docs.oracle.com/javase/tuto…):
- 同步是围绕一个称为内在锁或监视器锁的内部实体构建的。
- 每个对象都有一个与之相关的内在锁。按照惯例,线程必须在访问对象之前获得对象的监视器锁,然后在使用完对象后释放监视器锁。线程在获得锁和释放锁之间拥有锁。只要一个线程拥有监视器锁,其他线程就不能获得相同的锁。另一个线程在试图获取锁时将阻塞。
- 当线程释放锁时,在该操作和后续获取的相同锁之间建立happens-before关系。
- 所有隐式监控器都实现了可重入特性。可重入意味着锁被绑定到当前线程。线程可以安全地多次获得相同的锁,而不会陷入死锁。
在Java中,这是通过synchronized关键字或wait和notify完成的。
因此,监视器和锁不能比较差异,而是相互补充。Java中的每个对象都与一个监视器相关联,线程可以锁定或解锁该监视器。