Попытка получить основы многопоточности Java Я столкнулся с делом, которое не могу понять. Сообщество, поделитесь своим опытом, почему это происходит: у меня есть Runnable:
class ImproperStateWorker implements Runnable {
private int val = 0;
@Override
public void run() {
//Where are missing ticks?
for (int i = 0; i < 1000; i++) {
val++;
Thread.yield();
val++;
}
showDataState();
}
public void showDataState() {
System.out.print(Thread.currentThread() + " ; ");
System.out.println(val);
}
}
, который запускается через:
public class ImproperState {
public static void main(String[] args) {
ImproperStateWorker worker = new ImproperStateWorker();
for (int i = 0; i < 2; i++) {
Thread thread = new Thread(worker);
thread.start();
}
}
}
Я понимаю, чтоИдея состоит в том, чтобы сделать обе операции приращения атомарными, используя synchronized() {...}
, и так далее. Но меня смущает следующее: почему запуск этих двух Runnables (без синхронизации) не дает последовательного результата 4000 (1000 x 2 приращений на задачу)? Независимо от того, как контекст переключается между двумя задачами, я ожидаю, что задачи будут выполнять по 2000 шагов, мне все равно, какой будет порядок.
Однако вывод программы дает ~ 3.5K. Единственная идея, о которой я могу подумать, заключается в том, что «отсутствующие» приращения возникают потому, что некоторые из них создаются одновременно, так что val++
, вызываемый из двух потоков, фактически увеличивает значение на 1. Но это очень смутное предположение. Спасибо, что поделились своим опытом.