24542


マルチスレッドプログラミングを勉強するために、std::atomicを二つのスレッドでcompare_exchange_strongを用いて反転させる（すなわち、true->false,
false->trueに変換する）コードを書いたのですが、何回か繰り返し実行するとdeadlock?してしまうこと場合があることに気づきました。atomic操作であるため、deadlockは発生しないはずですがなぜこのような挙動が発生するのでしょうか？

Visual Studio 2015 Communityで現象が発生しています。

現象が発生するコードです。

[code]

    #include<atomic>
    #include<thread>
    #include<mutex>
    #include<iostream>
    
    std::atomic<bool> a_bool(false);
    
    // a_boolを1E5回反転させる関数
    // 結局は何もしないのと同じである。
    void func()
    {
        for (int j = 0; j < 1E5; ++j)
        {
            //ここのifがあやしい？
            if (a_bool.load(std::memory_order_acquire))
            {
                //a_bool.load = trueのため、true->falseへ書き換える
    
                bool expected = true;
                bool desired = false;
    
                // a_boolを反転させる
                // もし、a_boolがほかのthreadにより反転させられている場合は、
                // compare_exchange_strongにより、falseが返り値となり、whileが継続する。
                // 他のthreadが再度反転させるまでwhile loopで待ち続ける。
                do {
                    // 書き換えに失敗した場合はexpected = falseに
                    // 書き換えられるため、trueに戻す。
                    // これにより、ほかのthreadがa_boolをtrueに戻すまで待つ。
                    expected = true;
                } while (!a_bool.compare_exchange_strong(expected, desired));
            }
            else
            {
                //true branchの反対
    
                bool expected = false;
                bool desired = true;
    
                do { expected = false; } while (!a_bool.compare_exchange_strong(expected, desired));
            }
        }
    }
    
    int main(int argc, char const* argv[])
    {
    
            std::thread t1(func);
            std::thread t2(func);
    
            t1.join();
            t2.join();
    
            std::cout << "a_bool: " << a_bool.load(std::memory_order_acquire) << std::endl;
        return 0;
    }
    
[/code]

追記  
以下のように書き換えると問題が発生しなくなります。  
ということはwhile loopで問題が発生していることになります。

[code]

    if(!a_bool.compare_exchange_strong(expected, desired))
    {
        j--;
    }
    
[/code]


CC BY-SA 3.0
2016-05-03T16:49:00.970
24540
2016-05-03T23:02:27.657
2016-05-03T17:10:22.347
question
c++ c++11
std::atomic<bool>とcompare_exchange_strongでdeadlockしてしまう。


現状コードでは両スレッドともにtrue（またはfalse）を期待するwhileループに突入するシナリオがあり、設計上Dead Lockする可能性があります。

CASループ実装に2つの構造的な問題があります:

  * 最初のload結果だけで処理を分岐していること
  * whileループ内でdesired値を固定化していること


CC BY-SA 3.0
2016-05-03T22:57:02.540
24542
2016-05-03T23:02:27.657
2016-05-03T23:02:27.657
49
49
24540
answer