以下从某些队列实现中检索整数值的代码是否正确
Is the following code that retrieves an integer value from some queue implementation correct
我在网上读了一些东西。这是有关以下代码的问题。以下从某些队列实现中检索整数值的代码是否正确?答案是这样的:
Although the code above uses the queue as object monitor, it does not behave correctly in a multi-threaded environment. The reason for this is that it has two separate synchronized blocks. When two threads are woken up in line 6 by another thread that calls notifyAll(), both threads enter one after the other the second synchronized block. It this second block the queue has now only one new value, hence the second thread will poll on an empty queue and get null as return value.
我在想synchronized块会阻止不同的线程同时访问这个资源,是吗?谢谢。
public Integer getNextInt() {
Integer retVal = null;
synchronized (queue) {
try {
while (queue.isEmpty()) {
queue.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (queue) {
retVal = queue.poll();
if (retVal == null) {
System.err.println("retVal is null");
throw new IllegalStateException();
}
}
return retVal;
}
啊,我现在明白了..所以如果同时通知2个线程,一个进入块并轮询队列,第二个因为同步块而等待。然后当第二个线程进入时,队列已经空了......非常感谢。这是我在网上找到的例子。
问题比您的问题中描述的要广泛得多。它甚至不需要两个通知的线程(或 notifyAll
)来惹麻烦。问题是线程调度是不确定的。
考虑以下场景:
- 线程A进入第一个
synchronized
块,发现空队列等待
- 另一个线程将一个项目放入队列并通知一个线程。
- 线程 A 醒来并离开第一个
synchronized
块
- 线程B进入第一个
synchronized
块,发现非空队列,不等待!
- 线程 B 离开第一个
synchronized
块
所以现在,A
和 B
两个线程即将进入第二个 synchronized
块,顺序无关紧要,因为此时很明显只有一个线程可以消耗一个项目,另一个线程将失败(除非另一个线程恰好将某些东西放入中间的队列中)。
其实,它甚至不需要任何通知,例如如果两个线程在队列只包含一个元素时调用此方法。在都尝试执行第二个块之前,他们都可能执行第一个块发现队列非空。
最重要的是,如果您有某种条件,则针对该条件执行 wait
的代码(意味着检查该条件)和依赖于该条件的代码必须在一个 synchronized
块,或者在其他类型的锁的情况下,必须在整个代码中保持锁。
我在网上读了一些东西。这是有关以下代码的问题。以下从某些队列实现中检索整数值的代码是否正确?答案是这样的:
Although the code above uses the queue as object monitor, it does not behave correctly in a multi-threaded environment. The reason for this is that it has two separate synchronized blocks. When two threads are woken up in line 6 by another thread that calls notifyAll(), both threads enter one after the other the second synchronized block. It this second block the queue has now only one new value, hence the second thread will poll on an empty queue and get null as return value.
我在想synchronized块会阻止不同的线程同时访问这个资源,是吗?谢谢。
public Integer getNextInt() {
Integer retVal = null;
synchronized (queue) {
try {
while (queue.isEmpty()) {
queue.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (queue) {
retVal = queue.poll();
if (retVal == null) {
System.err.println("retVal is null");
throw new IllegalStateException();
}
}
return retVal;
}
啊,我现在明白了..所以如果同时通知2个线程,一个进入块并轮询队列,第二个因为同步块而等待。然后当第二个线程进入时,队列已经空了......非常感谢。这是我在网上找到的例子。
问题比您的问题中描述的要广泛得多。它甚至不需要两个通知的线程(或 notifyAll
)来惹麻烦。问题是线程调度是不确定的。
考虑以下场景:
- 线程A进入第一个
synchronized
块,发现空队列等待 - 另一个线程将一个项目放入队列并通知一个线程。
- 线程 A 醒来并离开第一个
synchronized
块 - 线程B进入第一个
synchronized
块,发现非空队列,不等待! - 线程 B 离开第一个
synchronized
块
所以现在,A
和 B
两个线程即将进入第二个 synchronized
块,顺序无关紧要,因为此时很明显只有一个线程可以消耗一个项目,另一个线程将失败(除非另一个线程恰好将某些东西放入中间的队列中)。
其实,它甚至不需要任何通知,例如如果两个线程在队列只包含一个元素时调用此方法。在都尝试执行第二个块之前,他们都可能执行第一个块发现队列非空。
最重要的是,如果您有某种条件,则针对该条件执行 wait
的代码(意味着检查该条件)和依赖于该条件的代码必须在一个 synchronized
块,或者在其他类型的锁的情况下,必须在整个代码中保持锁。