Странное поведение кодового кода
В настоящее время я изучаю Java concurrency. И я очень удивлен тем, как ведет себя код.
import java.util.concurrent.*;
public class Exercise {
static int counter = 0;
static synchronized int getAndIncrement() {
return counter++;
}
static class Improper implements Runnable {
@Override
public void run() {
for (int i = 0; i < 300; i++) {
getAndIncrement();
}
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 300; i++) {
executorService.submit(new Improper());
}
executorService.shutdown();
System.out.println(counter);
}
}
Должно ли оно выводить 90000 все время? Вместо этого результат различается все время.
Ответы
Ответ 1
-
executorService.shutdown()
не дождался завершения работы службы. Вам нужно позвонить awaitTermination
.
-
вы получаете доступ к counter
из основного метода без блокировки. Я думаю, что вы едва ли избежите гонки данных, если вы ожидаете, что служба-исполнитель отключится, но предупреждайте, что в общем случае вы должны синхронизировать все обращения к общей переменной, а не только записи, чтобы иметь какие-либо гарантии видимости от Модель памяти Java.
Ответ 2
Вам нужно убедиться, что все задачи успели закончить. Используйте awaitTermination
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 300; i++) {
executorService.submit(new Improper());
}
executorService.shutdown();
executorService.awaitTermination(2, TimeUnit.SECONDS);
System.out.println(counter);
}
Ответ 3
Вы не ждете завершения всех ваших подчиненных задач, см. javadoc для ExecutorService.html#shutdown. Таким образом, получение произвольного результата каждый раз является ожидаемым поведением.