【发布时间】:2011-03-22 16:42:33
【问题描述】:
Java 并发编程中的监视器是指什么?
当我读到“每个对象都关联了一个监视器”时,这是什么意思?
它是一个特殊的物体吗?
【问题讨论】:
-
+1 这让我了解了监视器是如何在 JVM 级别实现的。学到了新东西
-
@naikus 我希望与您分享详细信息 :)
标签: java multithreading concurrency monitor
Java 并发编程中的监视器是指什么?
当我读到“每个对象都关联了一个监视器”时,这是什么意思?
它是一个特殊的物体吗?
【问题讨论】:
标签: java multithreading concurrency monitor
监视器是控制对对象的并发访问的机制。
这允许你做:
线程 1:
public void a()
{
synchronized(someObject) {
// do something (1)
}
}
线程 2:
public void b()
{
synchronized(someObject) {
// do something else (2)
}
}
这可以防止线程 1 和 2 同时访问受监视(同步)部分。一个将启动,监视器将阻止另一个在第一个完成之前访问该区域。
这不是一个特殊的对象。它的同步机制位于类层次结构根:java.lang.Object。
还有wait 和notify 方法也将使用对象的监视器在不同线程之间进行通信。
【讨论】:
Class 静态方法的对象。如果您已经有一个同步的 method1() 并且您声明 method2() 同步,则不会创建新的监视器,实际上调用任一方法(在同一个对象上)将尝试锁定同一个监视器。这通常会吸引新人。
监视器是一个同时拥有锁和等待集的实体。在 Java 中,任何Object 都可以用作监视器。
有关监视器如何在 Java 中工作的详细说明,我建议阅读 Concurrent Programming in Java 的 Monitor Mechanics 部分(前面的链接显示 Google 书籍中的预览,并且该部分可供阅读)。
【讨论】:
Wakes up all threads that are waiting on this object's monitor.关于notifyall()时,我得到的是对象正在维护(在内部实体/对象的帮助下)所有线程都在等待锁定,那个内部实体/对象被称为监视器?跨度>
【讨论】:
在并发编程中,我们需要关注两件事
当一个进程/线程正在执行其临界区时,不允许其他进程执行其临界区。 (每个进程都有一个称为“关键部分”的代码段,其中访问共享数据。)
当线程试图通过协同工作来实现一个共同目标时,这些线程需要它们之间的合作。当他们专注于一个共同的目标时,他们需要同步。
监控器用于实现互斥和同步。
不要把这个临界区和临界区混为一谈,因为这里提到的临界区是对象级的,而不是线程级的。 共享数据被认为是临界区。
每个对象及其类都与一个监视器相关联。需要防止并发访问的对象的实例变量包括与对象相关联的监视器的关键区域和需要防止并发访问的类的实例变量/静态变量包括在关键区域中与类关联的监视器。
这个关键区域有一个锁保护,这个锁确保互斥。
Wait 集还与用于提供线程间协调的监视器相关联。
条目集用于保存已经请求锁但尚未获得锁的线程。
每个对象都与一个监视器相关联,并且此监视器有一个锁,每个线程都可以使用此锁锁定或解锁对象strong> 当它访问共享变量时。明确地说,这意味着一次只有一个线程可以在监视器上持有锁。任何其他试图锁定该 lock 的线程都会被阻止,直到它们能够获得 lock。当一个新线程尝试获取锁并且如果已经有一个线程拥有锁,那么该线程将等待条目集以获取锁。当获得锁的线程完成其临界区时,它将释放锁。所以下一个线程将获取锁,但下一个线程取自条目集,将由 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.
}
使用与监视器相关联的等待集和“等待并通知”或“信号并继续”机制来实现同步。当一个线程时,同步很重要需要一些数据处于特定状态,另一个线程负责将数据放入该状态,例如生产者/消费者问题
当一个线程调用对象的 wait() 方法时,该线程挂起并添加到等待集以等待,直到其他线程调用同一对象上的 notify() 或 notifyAll()。
notify() 方法用于唤醒处于特定对象的监视器的等待集中的线程。通知等待线程的方法有两种。
在生产者消费者问题中使用监视器实现同步的示例 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;
}
}
参考以下链接 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/
【讨论】:
【讨论】:
Java 语言和运行时系统通过使用监视器来支持线程同步。
监视器与特定数据项(条件变量)相关联,并用作对该数据的锁定。当一个线程持有某个数据项的监视器时,其他线程被锁定并且无法检查或修改数据。
【讨论】:
Monitor 是一种同步构造,它允许线程同时具有互斥和等待(阻塞)某个条件变为真的能力。
监视器还有一种机制,用于向其他线程发出信号,告知其条件已满足。它是一个同时拥有锁和等待集的实体。在 Java 中,任何 Object 都可以用作监视器。
在 Java 虚拟机中,每个对象和类在逻辑上都与一个监视器相关联。为了实现监视器的互斥功能,每个对象和类都关联了一个锁(有时称为互斥锁)。这在操作系统术语中称为信号量,互斥量是二进制信号量。
【讨论】:
http://journals.ecs.soton.ac.uk/java/tutorial/java/threads/monitors.html
monitor 与对象或数据成员相关联,当数据成员或对象进入同步块(临界区)时获取,退出时释放。
【讨论】: