如果在引用上调用,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();
在这种情况下,实际上会通知线程 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();