如果在引用上调用,wait() 是等待引用的对象还是引用本身?

Does wait() wait for the referenced object or the reference itself if called on a reference?

在这种情况下,实际上会通知线程 1(在等待引用而不是对象本身时)吗?

static Object lock=new Object();
//Thread 1:
Object reference=lock;
reference.wait();

//Thread 2:
lock.notify();

synchronized 方法评估给定同步块的表达式,以确定要获取的锁。那么wait、notify等需要在同一个对象上调用,但是是否使用同一个变量并不重要。代码计算表达式以获取对象。

现在线程 1 是否等待、被通知和唤醒取决于竞争条件的结果。如果thread1在thread2调用notify之前就进入了wait方法,那么thread2会一直等待,一旦thread2通知就唤醒。如果线程 2 在线程 1 进入 wait 方法之前调用了 notify,那么线程 1 将永远等待。

等待引用或该引用指向的对象是一回事,因为在对象上获得了锁。无论有多少引用,如果它们指向内存中的同一个对象,wait()、notify()、notifyall() 将无缝工作。查看下面的代码。

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

public class ProducerConsumer {

private Queue<Integer>      queue   = new ArrayBlockingQueue<>(10);
private LinkedList<Integer> list    = new LinkedList<>();
int                         limit   = 10;

public static void main(String[] args) {

    final ProducerConsumer pc = new ProducerConsumer();
    final ProducerConsumer pcRef = pc;

    Thread producer = new Thread(new Runnable() {
        int i = 1;

        @Override
        public void run() {
            while (true) {
                synchronized (pcRef) {
                    while (pc.limit == pc.list.size()) {
                        try {
                            pcRef.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    pc.list.add(i);
                    System.out.println("Producer @work : " + pc.list.size());
                    pcRef.notify();
                }

            }
        }
    });

    Thread consumer = new Thread(new Runnable() {

        @Override
        public void run() {
            while (true) {
                synchronized (pc) {
                    while (0 == pc.list.size()) {
                        try {
                            pc.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    int val = pc.list.removeFirst();
                    System.out.println("Consumer @work : " + pc.list.size() + " : " + val);
                    pc.notify();
                }

            }
        }
    });

    producer.start();
    consumer.start();

    try {
        producer.join();
        consumer.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

}

注释下面一行,您将看到消费者线程正在等待通知。

pc.list.add(i);
System.out.println("Producer @work : " + pc.list.size());
//pcRef.notify();