Java中并发编程中引用的监视器是什么?
当我读到“每个对象都有一个监视器”时,它意味着什么?
这是一个特殊的对象吗?
答案 0 :(得分:71)
监视器是控制对象的并发访问的机制。
这允许你这样做:
主题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
方法也会使用对象的监视器来进行不同线程之间的通信。
答案 1 :(得分:22)
监视器是拥有锁定和等待集的实体。在Java中,任何Object
都可以作为监视器。
有关监视器如何在Java中工作的详细说明,我建议您阅读Concurrent Programming in Java的 Monitor Mechanics 部分(上一个链接显示Google中的预览)书籍,该部分可供阅读)。
答案 2 :(得分:7)
答案 3 :(得分:4)
Java语言和运行时系统通过使用监视器支持线程同步 监视器与特定数据项(条件变量)相关联,并用作对该数据的锁定。当一个线程为某些数据项保存监视器时,其他线程将被锁定,无法检查或修改数据。
答案 4 :(得分:3)
答案 5 :(得分:2)
Monitor是一种同步构造,它允许线程同时具有互斥性,并且能够等待(阻止)某个条件变为真。
监视器还有一种机制,用于通知其他线程已满足其条件。它是一个拥有锁和等待集的实体。在Java中,任何Object都可以用作监视器。
在Java虚拟机中,每个对象和类在逻辑上与监视器关联。为了实现监视器的互斥功能,锁(有时称为互斥锁)与每个对象和类相关联。这在操作系统术语中称为信号量,互斥量是二进制信号量。
答案 6 :(得分:2)
在并发编程中,我们需要专注于两件事
当进程/线程执行其关键部分时,不允许其他进程执行其关键部分。 (每个进程都有一个称为“关键部分”的代码段,可以在其中访问共享数据。)
当线程试图通过共同努力实现共同目标时,这些线程需要它们之间的合作。当他们专注于一个共同的目标时,他们需要进行同步。
监视器用于实现互斥和同步。
不要将此临界区与临界区混淆,因为在这里,对象级中提到的临界区而不是线程级。共享数据被视为临界区。
每个对象及其类均与监视器关联。需要保护以防止并发访问的对象的实例变量包括与该对象关联的监视器的关键区域,以及需要保护以防止并发访问的类的实例变量/类的静态变量包括在该关键区域中。与班级关联的监视器。
此关键区域受锁保护,此锁可确保互斥。
等待集还与用于提供线程之间协调的监视器关联。
条目集用于保存已请求锁定的线程,而尚未被锁定的线程。
每个对象都与一个监视器关联,并且该监视器具有 锁 ,其中每个线程都可以使用此 lock 锁定或解锁对象。当访问共享变量时,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/
答案 7 :(得分:1)
http://journals.ecs.soton.ac.uk/java/tutorial/java/threads/monitors.html
monitor与对象或数据成员相关联,当数据成员或对象进入时获取的是同步块(临界区),并在退出时释放。