なぜスレッド間の同期にvolatileを使ってはいけない？


C言語で、2つのスレッドを同期するに、下記のようなプログラムを書きました。

[code]

    volatile int hoge = 0;
    //...
    void fuga1() // スレッド1で動いている
    {
        while (1)
        {
            while (hoge == 0) // 値が変わるまで待つ
                sleep(1);
            puts("fuga1!");
            hoge = 0;
        }
    }
    
    void fuga2() // スレッド2で動いている
    {
        while (1)
        {
            sleep(1000); // 1秒待つ
            hoge = 1;
        }
    }
    
[/code]

このプログラムは特に問題なく動いていて、1秒毎に「fuga1」が出力されています。

しかし、「これは`volatile`の正しい使い方ではない」、「スレッド間の同期に`volatile`を使うな」とは聞いたことあります。具体的になぜなのか、誰か教えていただけますでしょうか。




他の回答でも述べられていますが、`volatile`
はコンパイラの最適化の影響避けるためのもので、それ以外の何者でもなく、スレッドの同期をとるために用いるのは適切ではありません。

以下のブログ記事を参照すると、なぜ適切でないのかが理解できると思います。

<http://i-saint.hatenablog.com/entry/20101005/1286208402>

なお、スレッド間で同期をとりたい場合には、`条件変数（pthread_cond）`を用いるのが適切だと思います。 以下は `pthread_cond`
を用いた場合のコードです。

[code]

    int hoge = 0;
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    //...
    void fuga1() // スレッド1で動いている
    {
        while (1)
        {
            pthread_mutex_lock(&mutex);
            while (hoge == 0) // 値が変わるまで待つ
                pthread_cond_wait(&cond, &mutex);
            hoge = 0;
            pthread_mutex_unlock(&mutex);
            puts("fuga1!");
        }
    }
    
    void fuga2() // スレッド2で動いている
    {
        while (1)
        {
            sleep(1000); // 1秒待つ
            pthread_mutex_lock(&mutex);
            hoge = 1;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    
[/code]

