Если вы прервете линию
count.setCount (count.getCount () + 1);
в 3 отдельных строки, будет понятнее:
final int oldCount = count.getCount(); // a
final int newCount = oldCount + 1; // b
count.setCount(newCount); // c
Обратите внимание, что хотя операторы (a) и (c) синхронизированы, весь блок равен , а не . Таким образом, они все еще могут чередоваться, что означает, что поток A может вводить / выполнять оператор (a) после того, как поток B выполняет поток (a), но за до он завершает / вводит оператор (c). Когда это происходит, потоки (a) и (b) будут иметь одинаковые oldCount и, следовательно, пропускают одно приращение.
2
join () должен удостовериться, что оба потока A и Thread B заканчиваются перед печатью Причина в том, что вы получаете меньшее число, потому что, когда вы печатаете результаты, потоки A и B, возможно, еще не завершили работу. Другими словами, даже если вы синхронизируете идеально, без join (), у вас все равно будет число, намного меньшее, чем 2000.
3.
См. Ответ на вопрос 2.