0

次のコードがあるとします。

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が発生することを保証できないとすぐに、コードはスレッドセーフになります。

  1. どうすればこれを回避できますか?
  2. value_のタイプが、たとえば?の場合、事態は悪化しstructますか?
4

1 に答える 1

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_

于 2012-12-03T18:08:10.267 に答える