Spec-Zone .ru
спецификации, руководства, описания, API
|
Считайте простой class вызванным Counter
class Counter { private int c = 0; public void increment() { c++; } public void decrement() { c--; } public int value() { return c; } }
Counter
разрабатывается так, чтобы каждый вызов increment
добавит 1 к c
, и каждый вызов decrement
вычтет 1 из c
. Однако, если a Counter
на объект ссылаются от многократных потоков, интерференция между потоками может предотвратить это как ожидалось.
Интерференция происходит когда две операции, работающие в различных потоках, но действующие на те же самые данные, чередование. Это означает, что эти две операции состоят из многократных шагов, и последовательностей перекрытия шагов.
Это не могло бы казаться возможным для операций на экземплярах Counter
чередоваться, начиная с обеих операций на c
единственные, простые операторы. Однако, даже простые операторы могут преобразовать в многократные шаги виртуальной машиной. Мы не будем исследовать определенные шаги, которые делает виртуальная машина — достаточно знать что единственное выражение c++
может анализироваться в три шага:
c
.c
.Выражение c--
может анализироваться тот же самый путь, за исключением того, что второй шаг постепенно уменьшается вместо инкрементов.
Предположите, что Поток A вызывает increment
в приблизительно том же самом Потоке времени B вызывает decrement
. Если начальное значение c
0
, их чередованные действия могли бы следовать за этой последовательностью:
Распараллельте результат А, теряется, перезаписывается Потоком B. Это определенное чередование является только одной возможностью. При различных обстоятельствах это мог бы быть результат Б Потока, который теряется, или не могло быть никакой ошибки вообще. Поскольку они непредсказуемы, распараллеливают интерференционные ошибки, может быть трудным обнаружить и фиксировать.