This code is not guaranteed to be thread-safe on Win32, since Win32 guarantees atomicity only for properly-aligned 4-byte and pointer-sized values. bool
is not guaranteed to be one of those types. (It is typically a 1-byte type.)
For those who demand an actual example of how this could fail:
Suppose that bool
is a 1-byte type. Suppose also that your is_true
variable happens to be stored adjacent to another bool
variable (let's call it other_bool
), so that both of them share the same 4-byte line. For concreteness, let's say that is_true
is at address 0x1000 and other_bool
is at address 0x1001. Suppose that both values are initially false
, and one thread decides to update is_true
at the same time another thread tries to update other_bool
. The following sequence of operations can occur:
- Thread 1 prepares to set
is_true
to true
by loading the 4-byte value containing is_true
and other_bool
. Thread 1 reads 0x00000000.
- Thread 2 prepares to set
other_bool
to true
by loading the 4-byte value containing is_true
and other_bool
. Thread 2 reads 0x00000000.
- Thread 1 updates the byte in the 4-byte value corresponding to
is_true
, producing 0x00000001.
- Thread 2 updates the byte in the 4-byte value corresponding to
other_bool
, producing 0x00000100.
- Thread 1 stores the updated value to memory.
is_true
is now true
and other_bool
is now false
.
- Thread 2 stores the updated value to memory.
is_true
is now false
and other_bool
is now true
.
Observe that at the end this sequence, the update to is_true
was lost, because it was overwritten by thread 2, which captured an old value of is_true
.
It so happens that x86 is very forgiving of this type of error because it supports byte-granular updates and has a very tight memory model. Other Win32 processors are not as forgiving. RISC chips, for example, often do not support byte-granular updates, and even if they do, they usually have very weak memory models.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…