2

从使用仅同步方法(没有锁或 同步语句)接近于梅萨显示器,其中 有每个监视器一个条件变量的限度Programming Language Pragmatics, by Scott具有同步方法和同步语句的对象如何分别类似于监视器和条件关键区域?

Java对象(并且事实上具有同步语句的对象有时在Java中称为 监视器)。

为什么仅使用同步方法的Java对象与Mesa监视器非常相似,其中每个监视器有一个条件变量的限制?

“仅使用同步方法的Java对象”中没有条件变量是否正确?那么它怎么能像一个条件变量的监视器?

同样的道理,Java中的同步语句与等待在一个循环开始 类似于其中的 条件复检已经作出了明确一个CCR。因为通知也是明确的,所以在实现关键的 部分的每个退出时,Java实现不需要重新评估条件(或者明确地唤醒 线程) - 仅限于发生通知的那些条件。

为什么在Java中,与等待在循环开始 synchronized语句酷似CCR(有条件的关键区域),其中的条件复检已经作出了明确?

这是什么意思?“因为通知也是显式的,Java实现不需要在关键部分每次退出时重新评估条件(或唤醒显式执行的线程) - 只有那些发生通知的部分”?

谢谢。

+0

*“为什么X像Y'” *,因为它们看起来相似,又称他们在行为方式相似。如果你了解X的行为,那么你很快就会明白Y的行为。你是否理解“Mesa监视器”或“CCR”?如果不是这样,比较对理解Java监视器没有帮助,而且任何详细的逐个功能比较都不会对您有所帮助。如果你理解这些,为什么你不认为它们类似于Java特性? – Andreas

+0

如果您使用关于显示器的一些常识,您实际上不需要知道Mesa:M​​esa显示器是显示器。 – Ben

回答

1

所有这一切都是说,在Java中,内在锁具有烘焙到它们中的条件。将其与ReentrantLock进行对比,您可以在其中明确地使用相同的锁定分隔条件。

如果你有单独的条件,那么你可以表示一个给定的条件,并知道只有在该条件的等待集中的线程才会收到它。如果您没有单独的条件对象,则在收到通知后,您必须检查该条件是否适用于您。

一个这样的例子将是一个固定大小的阻塞队列。如果您查看ArrayBlockingQueue,它将与ReentrantLock一起实现,以便放置和使用单独的条件对象。如果这是使用Queue对象上的内部锁来实现的,那么它必须使用notifyAll来唤醒等待的线程,然后这些线程必须测试它们从等待中醒来的状态,以确定它是否与它们相关。

这里是使用固有锁写入的阻塞队列。如果使用通知,那么单个线程将被调度程序唤醒,并且(因为线程可能正在等待放置或等待采取),它可能是也可能不是通知相关的。为了确保该通知不会丢失所有等待的线程得到通知:

public class Queue<T>{ 

    private final int maxSize; 
    private List<T> list = new ArrayList<>(); 
    public Queue(int maxSize) { 
     this.maxSize = maxSize; 
    } 

    public synchronized T take() throws InterruptedException { 
     while (list.size() == 0) { 
      wait(); 
     } 
     notifyAll(); 
     return list.remove(0)(
    } 

    public synchronized void put(T entry) throws InterruptedException { 
     while (list.size() == maxSize) { 
      wait(); 
     } 
     list.add(entry); 
     notifyAll(); 
    } 
}