什么是Java中的监视器?

xde*_*000 115 java concurrency multithreading monitor

什么是Java中并发编程中引用的监视器?

当我读到"每个对象都有一个监视器"这是什么意思?

这是一个特殊的对象吗?

Pab*_*ruz 80

监视器是控制对象的并发访问的机制.

这允许你这样做:

线程1:

public void a()
{
    synchronized(someObject) {
        // do something (1)
    }
}
Run Code Online (Sandbox Code Playgroud)

线程2:

public void b()
{
    synchronized(someObject) {
        // do something else (2)
    }
}
Run Code Online (Sandbox Code Playgroud)

这可以防止线程1和2同时访问受监视(同步)部分.一个将开始,监视器将阻止另一个在第一个完成之前访问该区域.

这不是一个特殊的对象.它的同步机制放在类层次结构根目录:java.lang.Object.

也有waitnotify,也将使用对象的监视器通信不同的线程之间的方法.

  • 和@Pablo - 没有一个方法的监视器; 监视器仅存在于对象中,对象是大多数方法的封闭实例,或者是静态方法的相应"类"对象.如果已经有一个synchronized method1()并且声明了method2()synchronized,则不会创建新的监视器,实际上调用任一方法(在同一对象上)将尝试锁定同一个监视器.这往往会吸引新人. (28认同)
  • 呃,不完全是.无论其他什么,每个对象都自动拥有一个与之关联的监视器(互斥锁).当您声明一个方法同步时,您声明运行时必须在该方法的执行开始之前获取对象监视器上的锁(并且必须在控制返回到调用代码之前释放锁). (25认同)
  • 它的操作系统类重新开始......减去夜惊...... (4认同)

JRL*_*JRL 24

监视器是拥有锁定等待集合的实体.在Java中,任何Object可以充当监视器.

有关监视器如何在Java中工作的详细说明,我建议阅读Java中的Concurrent ProgrammingMonitor Mechanics部分(上面的链接显示了Google书籍中的预览,该部分可供阅读).


小智 9

  1. 监视器是一种概念/机制,不仅限于Java语言;
  2. "在并发编程中,监视器是一个旨在由多个线程安全使用的对象或模块";
  3. 正如每个读者都知道的那样,Java中的每个对象都是java.lang.Object的子类.java人员以这样的方式创建了java.lang.Object,它具有使Java程序员能够将任何对象用作监视器的特性和特性.例如,每个对象都有一个等待队列,一个重新进入队列以及等待和通知方法,使其成为监视器;
  4. 在这里阅读监视器.


RCv*_*ram 8

在并发编程中,我们需要关注两件事

  1. 相互排斥

当进程/线程正在执行其临界区时,不允许其他进程执行其临界区。(每个进程都有一个称为“临界区”的代码段,其中访问共享数据。)

  1. 同步

当线程试图通过协同工作来实现一个共同的目标时,这些线程需要它们之间的合作。当他们专注于一个共同的目标时,他们需要同步。

监视器用于实现互斥和同步。


如何轻松理解Monitor?

监视器的高级视图

不要将此临界区与临界区混淆,因为这里提到的临界区是对象级的,而不是线程级的。共享数据被视为关键区域。

每个对象及其类都与一个监视器相关联。需要防止并发访问的对象的实例变量包括与对象关联的监视器的关键区域和需要防止并发访问的类的实例变量/类的静态变量包括在关键区域中与类关联的监视器。

  • 这个关键区域用锁保护,这个锁确保互斥。

  • 等待集还与用于在线程之间提供协调的监视器相关联。

  • 一个条目集用于保存已经请求锁定并且尚未获得锁定的线程。

Monitor上如何实现互斥?


每个对象都与一个监视器相关联,并且这个监视器有一个,每个线程在访问共享变量时可以使用这个来锁定或解锁对象。明确地,这意味着一次只有一个线程可以持有监视器上的。任何其他试图锁定该锁的线程都将被阻塞,直到它们能够获得该. 当一个新线程尝试获取锁并且如果已经有一个线程拥有该锁,则该线程将等待条目集以获取该锁。当获得锁的线程完成其临界区时,它将释放锁。因此,下一个线程将获取锁,但下一个线程是从条目集中获取的,并将由 JVM 根据某些标准(如 FIFO)确定。

在这里,我们实现了互斥,因为我们为对象提供了对线程的独占访问权限,并且不允许任何其他线程进入它们的临界区。

使用监视器实现互斥的示例java代码

  class Counter
      {
            private int count = 0;
            public void synchronized Increment() {
                int n = count;
                count = n+1;
            } //Here synchronized is used to indicate those things should be done sequentially.
      }

Run Code Online (Sandbox Code Playgroud)

如何通过 Monitor 实现协调/同步?

使用与监视器相关联的等待集和“等待并通知”或“信号并继续”机制来实现同步。 当一个线程需要一些数据处于特定状态而另一个线程负责将数据进入该状态(例如生产者/消费者问题)时,同步很重要

当线程调用针对对象的 wait() 方法时,该线程将挂起并添加到等待集以等待其他线程对同一对象调用 notify() 或 notifyAll() 。

notify() 方法用于唤醒处于特定对象监视器的等待集中的线程。有两种通知等待线程的方法。

  • notify() --> 对于等待设置的所有线程,notify() 方法通知他们中的任何人任意唤醒。确切地选择要唤醒的线程是不确定的,并且取决于 JVM。
  • notifyAll() --> 这个方法只是唤醒所有在等待集上等待的线程。在当前线程释放此对象上的锁之前,被唤醒的线程将无法继续。被唤醒的线程将以通常的方式与可能正在积极竞争同步的任何其他线程竞争。

在生产者消费者问题中使用监视器实现同步的示例 Java 代码

class Buffer {
            private char [] buffer;
            private int count = 0, in = 0, out = 0;

            Buffer(int size)
            {
                 buffer = new char[size];
            }
 
            public synchronized void Put(char c) {
                 while(count == buffer.length) 
                 {
                      try { wait(); }
                      catch (InterruptedException e) { } 
                      finally { } 
                 } 
                 System.out.println("Producing " + c + " ...");
                 buffer[in] = c; 
                 in = (in + 1) % buffer.length; 
                 count++; 
                 notify(); 
            }
    
            public synchronized char Get() {
                 while (count == 0) 
                 {
                      try { wait(); }
                      catch (InterruptedException e) { } 
                      finally { } 
                 } 
                 char c = buffer[out]; 
                 out = (out + 1) % buffer.length;
                 count--;
                 System.out.println("Consuming " + c + " ..."); 
                 notify(); 
                 return c;
            }
      }
Run Code Online (Sandbox Code Playgroud)

请参阅以下链接 http://www.csc.villanova.edu/~mdamian/threads/javamonitors.html#:~:text=Java%20associates%20a%20monitor%20with,the%20monitor%20for%20that%20object https: //howtodoinjava.com/java/multi-threading/how-to-use-locks-in-java-java-util-concurrent-locks-lock-tutorial-and-example/