&引用;“监测”;在java线程中

&引用;“监测”;在java线程中,java,Java,我在不同的博客上读到了关于显示器的不同内容。所以我现在有点困惑 据我所知,monitor是一个确保只有一个线程在关键部分执行代码的人。那么,如果我们有3个同步的方法/块,那么我们会有3个监视器来确保只有一个线程在关键部分中吗 如果上述情况属实,那么为什么说在Java中,每个对象都有一个与其关联的监视器?应该注意的是,每个同步块都与监视器关联。对块使用同步时,请指定要锁定的对象。在这种情况下,该对象的监视器用于锁定 在将synchronized与方法一起使用时,您不会指定要锁定的对象,而是隐含了此

我在不同的博客上读到了关于显示器的不同内容。所以我现在有点困惑

据我所知,monitor是一个确保只有一个线程在关键部分执行代码的人。那么,如果我们有3个同步的方法/块,那么我们会有3个监视器来确保只有一个线程在关键部分中吗


如果上述情况属实,那么为什么说在Java中,每个对象都有一个与其关联的监视器?应该注意的是,每个同步块都与监视器关联。

对块使用
同步时,请指定要锁定的对象。在这种情况下,该对象的监视器用于锁定


在将
synchronized
与方法一起使用时,您不会指定要锁定的对象,而是隐含了
对象。同样,此
的监视器用于锁定


因此,对象有监视器,而同步方法/块没有自己的监视器,而是使用特定对象的监视器。

什么是监视器?

监视器是一个线程可以抓取和保持的东西,防止所有其他线程抓取同一个监视器,并迫使它们等待监视器被释放。这就是
synchronized
块所做的

这些监视器首先来自哪里?

答案是:来自任何Java对象。当你写作时:

Object foo = new Object();
synchronized (foo) {
  System.out.println("Hello world.");
}
…这意味着:当前线程将首先抓取与存储在变量
foo
中的对象关联的监视器,并在它打印“Hello world”时按住它,然后释放它

为什么每个Java对象都有一个与之关联的监视器?


没有技术上的理由这样做。这是Java早期版本中做出的一项设计决策,现在进行更改已经太迟了(尽管一开始它令人困惑,如果人们不小心,它确实会导致问题)。

在Java编程环境中,监视器是Java对象上的内在锁(内在意味着“内置”)。线程若要在对象上输入任何同步实例方法,必须首先获取该对象上的内在锁。线程若要在类上输入任何同步静态方法,必须首先获取该类上的内在锁

以下是监视器在中的定义:

同步是围绕称为内在锁或监视锁的内部实体构建的。(API规范通常将该实体简单地称为“监视器”)

监视器属于一个对象而不是单个块有一个很好的理由:监视器在那里是为了保护对象的状态。对象的设计应该是,使得实例变量很可能最终被多个方法引用;为了保证对象始终处于一致状态,安全的做法是一次只允许在该对象上执行一个同步方法

“监视器”一词来源于。请参阅,它认为Java实际上并没有实现监视器:

Gosling(1996,第399页)声称Java使用监视器来同步线程。不幸的是,仔细检查发现Java不支持监视器概念:

  • 除非声明为已同步,否则Java类方法是不同步的

  • 除非声明为私有,否则Java类变量是公共的(在包中)

同一篇文章的另一句话:

未能给线程交互赋予足够的意义是Java的一个非常深刻的缺陷,它破坏了监视器概念的概念完整性


是的,但是每个同步块都有一个与其关联的监视器(通过
synchronized(monitor){…}声明)
,并且该监视器是一个对象。那么您是说监视器只是我们试图访问的共享资源吗?您可以将监视器视为对象的一部分,它可以记住哪个线程当前正在执行在其上同步的块。它还可以记住线程进入基于它的同步块的次数同一监视器(重入锁).Monitor还记得其他线程的列表,这些线程当前正在等待它通知它们应该继续它们的代码。那么,如果使用同步方法,会发生什么情况。我们没有与之关联的对象,因此不会使用监视器?@DeepakKumar A
synchronized
方法相当于
synchronic泽德(这个){}
,而静态同步方法使用类对象作为其监视器。感谢您的回复。我还有最后一件事,如果我问了这么多问题,我很抱歉。如果我没有弄错,静态同步方法与类对象无关。那么在这种情况下,我们如何将类对象作为监视器?@DeepakKumar
SomeClass.class
也是一个对象(确切地说,它是
Class
Class的实例),该对象用于同步静态方法。