假设我有以下代码:
struct Obj {
mutable bool valueIsCached_;
mutable int value_;
const int parameter_;
Obj (int parameter) : valueIsCached_ (false), parameter_ (parameter) {
}
int getValue () const {
if (!valueIsCached) {
value_ = calculateValue (); // #1
valueIsCached_ = true; // #2
}
return value_;
}
private:
int calculateValue () {
/* calculate value based on parameter and return it;
return value only depends on value of parameter_
(no side effects; no dependence on global state)
*/
}
};
如果编译器没有对标记为#1和#2的行重新排序,则此代码显然是线程安全的。可能发生的最糟糕的事情是value_
的多次计算。但是,只要我们无法保证在#1之后发生#2,代码就会变得不安全。
value_
的类型是struct
,那么事情会变得更糟吗?答案 0 :(得分:1)
您需要插入障碍物。这是VC ++的代码:
int getValue () const {
if (!valueIsCached_) {
value_ = calculateValue (); // #1
_WriteBarrier(); // force value_ to be written first.
valueIsCached_ = true; // #2
}
return value_;
}
请注意,假设calculateValue
是线程安全的,因为它可以由多个线程调用,并且不止一次写入value_
和valueIsCached_
是安全的。