Одна интересная вещь произошла со мной, когда я пытался сделать простую демонстрацию, используя wait()
с synchronized
, следующая демонстрация дает мне неожиданное выходы.
public class WaitZero {
private static AtomicInteger num = new AtomicInteger(0);
private static boolean consumed = false;
public static void main(String... args) throws Exception {
ThreadPoolExecutor threadPoolExecutor = getMyCachedThreadPool();
for (int i = 0; i < 5; i++) {
threadPoolExecutor.submit(WaitZero::send);
threadPoolExecutor.submit(WaitZero::receive);
}
threadPoolExecutor.shutdown();
threadPoolExecutor.awaitTermination(60, TimeUnit.SECONDS);
}
private static synchronized void send() {
try {
while (!isConsumed()) {
num.wait();
}
} catch (InterruptedException ignored) {
ignored.printStackTrace();
}
num.incrementAndGet();
System.out.println(Thread.currentThread().getName() + " number updated: " + num);
setConsumed(false);
num.notifyAll();
}
private static synchronized void receive() {
try {
while (isConsumed()) {
num.wait();
}
} catch (InterruptedException ignored) {
ignored.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " number received: " + num);
setConsumed(true);
num.notifyAll(); // ToDo: when to use notify?
// ToDo: what is monitor?
}
private static boolean isConsumed() {
return consumed;
}
private static void setConsumed(boolean consumed) {
WaitZero.consumed = consumed;
}
}
Его вывод нестабилен, но одним из типичных может быть
shared-pool-0 number received: 0
shared-pool-1 number updated: 1
shared-pool-0 number received: 1
shared-pool-1 number updated: 2
shared-pool-1 number received: 2
shared-pool-2 number updated: 3
В то время как я ожидал, что
shared-pool-1 number received: 0
shared-pool-0 number updated: 1
shared-pool-3 number received: 1
shared-pool-2 number updated: 2
shared-pool-1 number received: 2
shared-pool-0 number updated: 3
shared-pool-2 number received: 3
shared-pool-3 number updated: 4
shared-pool-5 number received: 4
shared-pool-4 number updated: 5
Получен правильный результаткогда я использую WaitZero.class
вместо num
на wait()/notifyAll()
.
Я прочитал вокруг, и кажется, что всегда нужно использовать три из них на одном и том же объекте , чтобы гарантировать правильность.
Угадай: Если не все из них на одном и том же объекте, между notifyAll()
и синхронизированной блокировкой существует особый случай.Но что это?
Любая помощь будет оценена;)