成员变量锁上的线程行为
Thread behaviour on member variable lock
当运行以下代码时,抛出IllegalMonitorStateException。
class Consumer {
private int capacity = 5;
private Queue<Integer> queue = new PriorityQueue<Integer>(capacity);
class ConsumerWaitNotify implements Runnable {
public void run() {
try {
consumeItem();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void consumeItem() {
try {
synchronized (queue) { //Line 1
while(queue.size() == 0) {
System.out.format("%n%s: Waiting..Empty Queue, Size: %d%n", Thread.currentThread().getName(),
queue.size());
wait(); //Line 2
}
int popItem = queue.poll();
System.out.format("%n%s: Consumes Item: %d, Size: %d", Thread.currentThread().getName(),
popItem, queue.size());
notify();
}
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ConsWaitNotify {
public static void main(String[] args) {
Consumer pc = new Consumer();
Consumer.ConsumerWaitNotify cwn = pc.new ConsumerWaitNotify();
Thread consumer = new Thread(cwn, "CONSUMER");
consumer.start();
}
}
错误如下:
CONSUMER: Waiting..Empty Queue, Size: 0
Exception in thread "CONSUMER" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at com.threadconcurrency.lock.prodcons.Consumer$ConsumerWaitNotify.consumeItem(ConsWaitNotify.java:67)
at com.threadconcurrency.lock.prodcons.Consumer$ConsumerWaitNotify.run(ConsWaitNotify.java:52)
at java.lang.Thread.run(Thread.java:619)
我在调试的时候发现,当执行到第2行wait()命令时,线程不是退出runnable状态,而是跳转到第1行执行,并执行了2次。因此它抛出异常。
我假设在wait之后,线程可能释放了对象(queue)的锁,但仍然持有对象class ConsumerWaitNotify,这就是它如此表现的原因。
我通过 Consumer 的单独 class 和方法 consumeItem() 实现了我想要的 synchronised(this) 代码和 ConsumerWaitNotify 以 Consumer 对象作为成员。
但这有什么不对的。我仍然很困惑,无法预测确切的行为。谁能帮帮我?
您正在同步变量 queue
,但在 this
对象上调用 wait()
和 notify()
。您要么需要使用 synchornized(this)
保持锁定,要么调用 queue.wait()
和 queue.notify()
以确保您通知您拥有锁定的同一个监视器。你可以看看Guarded Blocks docs.
请注意,您不需要自己实现队列。 JDK 提供了一些 java.util.concurrent.BlockingQueue
实现:
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
当运行以下代码时,抛出IllegalMonitorStateException。
class Consumer {
private int capacity = 5;
private Queue<Integer> queue = new PriorityQueue<Integer>(capacity);
class ConsumerWaitNotify implements Runnable {
public void run() {
try {
consumeItem();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void consumeItem() {
try {
synchronized (queue) { //Line 1
while(queue.size() == 0) {
System.out.format("%n%s: Waiting..Empty Queue, Size: %d%n", Thread.currentThread().getName(),
queue.size());
wait(); //Line 2
}
int popItem = queue.poll();
System.out.format("%n%s: Consumes Item: %d, Size: %d", Thread.currentThread().getName(),
popItem, queue.size());
notify();
}
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ConsWaitNotify {
public static void main(String[] args) {
Consumer pc = new Consumer();
Consumer.ConsumerWaitNotify cwn = pc.new ConsumerWaitNotify();
Thread consumer = new Thread(cwn, "CONSUMER");
consumer.start();
}
}
错误如下:
CONSUMER: Waiting..Empty Queue, Size: 0
Exception in thread "CONSUMER" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at com.threadconcurrency.lock.prodcons.Consumer$ConsumerWaitNotify.consumeItem(ConsWaitNotify.java:67)
at com.threadconcurrency.lock.prodcons.Consumer$ConsumerWaitNotify.run(ConsWaitNotify.java:52)
at java.lang.Thread.run(Thread.java:619)
我在调试的时候发现,当执行到第2行wait()命令时,线程不是退出runnable状态,而是跳转到第1行执行,并执行了2次。因此它抛出异常。
我假设在wait之后,线程可能释放了对象(queue)的锁,但仍然持有对象class ConsumerWaitNotify,这就是它如此表现的原因。
我通过 Consumer 的单独 class 和方法 consumeItem() 实现了我想要的 synchronised(this) 代码和 ConsumerWaitNotify 以 Consumer 对象作为成员。
但这有什么不对的。我仍然很困惑,无法预测确切的行为。谁能帮帮我?
您正在同步变量 queue
,但在 this
对象上调用 wait()
和 notify()
。您要么需要使用 synchornized(this)
保持锁定,要么调用 queue.wait()
和 queue.notify()
以确保您通知您拥有锁定的同一个监视器。你可以看看Guarded Blocks docs.
请注意,您不需要自己实现队列。 JDK 提供了一些 java.util.concurrent.BlockingQueue
实现:
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.