简体   繁体   English

具有同步方法和同步语句的对象如何分别类似于监视器和条件关键区域?

[英]How do objects with synchronized methods and synchronized statements resemble monitors and conditional critical regions respectively?

From Programming Language Pragmatics, by Scott 摘自Scott的《编程语言语用学》

Java objects that use only synchronized methods (no locks or synchronized statements) closely resemble Mesa monitors in which there is a limit of one condition variable per monitor (and in fact objects with synchronized statements are sometimes referred to as monitors in Java). 仅使用同步方法 (不使用锁或同步语句)的Java对象Mesa监视器非常相似,在Mesa监视器中,每个监视器都有一个条件变量的限制 (实际上,具有同步语句的对象有时在Java中称为监视器)。

Why are Java objects that use only synchronized methods closely resemble Mesa monitors in which there is a limit of one condition variable per monitor? 为什么仅使用同步方法的Java对象与Mesa监视器非常相似,其中每个监视器只能有一个条件变量?

Is it correct that there is no condition variable in "Java objects that use only synchronized methods"? 在“仅使用同步方法的Java对象”中没有条件变量是否正确? So how can it resembles a monitor with one condition variable? 那么,它如何像一个带有一个条件变量的监视器呢?

By the same token, a synchronized statement in Java that begins with a wait in a loop resembles a CCR in which the retesting of conditions has been made explicit . 同样, Java中以循环等待开始的同步语句类似于CCR,在该CCR中,条件的重新测试已明确 Because notify also is explicit, a Java implementation need not reevaluate conditions (or wake up threads that do so explicitly) on every exit from a critical section—only those in which a notify occurs. 由于notify也是显式的,因此Java实现无需在临界区的每次退出时都重新评估条件(或显式唤醒执行此操作的线程),而只需重新评估发生通知的条件。

Why does a synchronized statement in Java that begins with a wait in a loop resembles a CCR (conditional critical region) in which the retesting of conditions has been made explicit? 为什么在Java中以循环等待开始的同步语句为何类似于CCR(条件关键区域),在其中明确说明了条件的重新测试?

What does it mean by "Because notify also is explicit, a Java implementation need not reevaluate conditions (or wake up threads that do so explicitly) on every exit from a critical section—only those in which a notify occurs"? 这是什么意思?“因为通知也是显式的,因此Java实现不需要在临界区的每次退出时(仅在发生通知的情况下)重新评估条件(或显式唤醒执行此操作的线程”)?

Thanks. 谢谢。

All this is saying is that in Java intrinsic locks have the condition baked into them. 这一切都说明,在Java中,内在锁具有嵌入其中的条件。 Contrast this with ReentrantLock where you can explicitly have separate conditions with the same lock. 将此与ReentrantLock进行对比,您可以在其中使用相同的锁显式地拥有单独的条件。

If you have separate conditions then you can signal a given condition and know only threads in the wait set for that condition will receive it. 如果您有单独的条件,则可以发出给定条件的信号,并且仅知道等待条件集中的线程会收到该条件。 If you don't have separate condition objects then upon being notified you have to check to see if that condition applies to you. 如果您没有单独的条件对象,则在收到通知后,您必须检查该条件是否适用于您。

An example of this would be a fixed size blocking queue. 一个示例是固定大小的阻塞队列。 If you look at ArrayBlockingQueue, it's implemented with ReentrantLock so that putting and taking use separate condition objects. 如果您查看ArrayBlockingQueue,它是通过ReentrantLock实现的,因此可以放置和使用单独的条件对象。 If this was implemented using the intrinsic lock on the Queue object it would have to use notifyAll to wake up waiting threads, which would then have to test the condition they woke up from waiting on to find out if it was relevant to them. 如果这是通过使用Queue对象上的固有锁实现的,则必须使用notifyAll来唤醒等待的线程,然后必须测试它们从等待中醒来的条件,以找出是否与它们相关。

Here is a blocking queue written using an intrinsic lock. 这是使用内部锁编写的阻塞队列。 If notify was used then a single thread would be woken by the scheduler and (since threads could be waiting to put or waiting to take) it might or might not be one that the notify was relevant to. 如果使用了notify,则调度程序将唤醒单个线程,并且(由于线程可能正在等待放入或等待接收),它可能与通知相关,也可能不是。 To make sure the notification doesn't get lost all the waiting threads get notified: 为了确保通知不会丢失,所有等待线程都会得到通知:

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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM