java线程中的“Monitor”

时间:2015-10-06 19:56:41

标签: java

我在不同的博客中读过有关显示器的不同内容。所以我现在有点困惑。

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

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

3 个答案:

答案 0 :(得分:7)

什么是显示器?

监视器是线程可以抓取并保持的东西,防止所有其他线程抓取同一个监视器并强制它们等到监视器被释放。这是synchronized块的作用。

这些显示器首先来自哪里?

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

Object foo = new Object();
synchronized (foo) {
  System.out.println("Hello world.");
}

......这意味着:当前线程将首先获取与存储在变量foo中的对象关联的监视器,并在打印时保持它" Hello world",然后释放它

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

没有技术原因可以这样做。这是在Java的早期版本中做出的设计决定,现在改变为时已晚(尽管一开始会让人感到困惑,如果人们不小心,它确实会引起问题)。

答案 1 :(得分:4)

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

在方法中使用synchronized时,您没有指定要锁定的对象,而是暗示了this对象。同样,this的监视器用于锁定。

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

答案 2 :(得分:0)

在Java编程的上下文中,监视器是Java对象上的内部锁(其中内部表示“内置”)。为了使线程在对象上输入任何同步实例方法,它必须首先获取该对象上的固有锁。为了使线程在类上输入任何同步的静态方法,它必须首先获取该类上的固有锁。

这是在the Java tutorial中定义监视器的方式:

  

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

因此,Java中的“监视器”是“内在锁”的同义词。

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

术语“监视器”来自Concurrent Pascal,尽管其含义似乎有很大不同。参见Per Brinch Hansen's paper "Java's Insecure Parallelism",该文章认为Java实际上并未实现监视器:

  

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

     
      
  • 除非将它们声明为   同步,Java类方法不同步。

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

  •   

同一篇论文的另一句话:

  

未能给线程交互足够的含义是Java的一个非常深层的缺陷,它削弱了监视器概念的概念完整性。

我尽量避免使用“显示器”一词,而是更精确地使用“内在锁”。但是“监控器”出现在JLS中,无法避免。

请记住,当Java发明时,它并不是以服务器端语言的想法来实现疯狂吞吐量的大型应用程序。它是针对嵌入式编程的,它需要多线程才能处理来自不同输入的事件,但是效率并不是重中之重,并且像Concurrent Pascal中强调的安全性没什么大不了的。内在锁的设计易于使用-在退出方法或块时无法解锁监视器。但是它们并不能给您最大的控制权。例如,当您希望多个条件与同一个锁关联时,它们就不是很好。

对于需要更细粒度和更多控制的任何情况,请使用其他解决方案,例如ReentrantLock。