インクリメントはアトミックではありません。値を読み取り、インクリメントされた値を書き出します。これら 2 つの操作の間に、もう一方のスレッドが複雑な方法で合計を操作できます。
値の範囲は、実際には 100 から 200 ではありません。この範囲は、スレッドが交代するか、各読み取りを同時に実行するという誤った仮定に基づいています。さらに多くの可能なインターリーブがあり、そのうちのいくつかは著しく異なる値を生成します。最悪のケースは次のとおりです (x
式で使用される暗黙的な一時を表しますsum++
)。
Thread A Thread B
---------------- ----------------
x ← sum (0)
x ← sum (0)
x + 1 → sum (1)
x ← sum (1)
x + 1 → sum (2)
⋮
x ← sum (98)
x + 1 → sum (99)
x + 1 → sum (1)
x ← sum (1)
x ← sum (1)
x + 1 → sum (2)
⋮
x ← sum (99)
x + 1 → sum (100)
x + 1 → sum (2)
したがって、可能な最小値は 2 です。簡単に言えば、2 つのスレッドは互いのハードワークを元に戻します。スレッド B はスレッド A にゼロをフィードできないため、2 を下回ることはできません。スレッド A は、インクリメントされた値しか出力できません。スレッド A は、スレッド B が与えた 1 をインクリメントする必要があります。