Метод flipDone
выполняется компьютером в три этапа:
Read the value of memory location labeled done into ALU
Flip the value (i.e true -> false or false -> true)
Write the new value into the memory location done
В Java фрагмент кода может потенциально вызываться в нескольких потоках.Эти потоки должны рассматриваться как выполняющие код одновременно .
Скажем, область памяти с меткой done
изначально содержит значение false
.Рассмотрим два потока, вызывающих flipDone
, в результате чего получается следующая последовательность шагов:
Thread 1 Thread 2
-----------------------------------------------------------------------
Read value of done, false
Invert that value to true
Write the new value, true, to done
Read value of done, now true
Invert that value to false
Write the new value, false, to done
Метод flipDone
вызывался дважды.done
перешел от false
к true
, а затем снова к false
- как и следовало ожидать.Но поскольку потоки выполняются одновременно, это не единственный порядок шагов.Вместо этого рассмотрим следующий порядок:
Thread 1 Thread 2
-----------------------------------------------------------------------
Read value of done, false
Invert that value to true Read value of done, false
Write the new value, true, to done Invert that value to true
Write the new value, true, to done
Пока первый поток инвертирует прочитанное значение, второй поток одновременно читает значение.Аналогичным образом, пока первый поток записывает значение в память, второй поток инвертирует значение , которое он считал .Когда Thread 2
заканчивается, значение done
будет истинным.Здесь, хотя flipDone
был вызван дважды, done
был перевернут только один раз!Похоже, что одно из обновлений было потеряно 1030 *.Это проблема, о которой вас предупреждает книга.