http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Atomic-Builtins.html
次のコードはvarの値をアトミックに増加すると思います。
volatile int var = 0;
__sync_fetch_and_add( &var, 1 )
上記のコードを次のように理解しましたlogic:
ただし、以下もアトミックかどうかは疑問です
volatile int var = 0;
volatile int num = 1;
__sync_fetch_and_add( &var, num )
として解釈される可能性があるため
#2が実行された後、#3の前に、CPU /スレッドが中断され、別のCPU /スレッドが変数numの値を更新します。
つまり、gccの_sync*()を使用する場合、2番目の引数として定数ではなく変数を使用できますか?
それは原子性を壊しませんか?
操作は実際には2つの操作です。
__sync_fetch_and_add( &var, num )
num
のロードはアトミックです。 var
への追加はアトミックです。ただし、2つのアトミック操作を組み合わせても、アトミック操作は行われません。これが、ロックのない新しいデータ構造を発明することが非常に難しい理由です。 一般的に、2つのスレッドセーフ操作は、合成時に必ずしもスレッドセーフ操作になるとは限りません。これが、正しいマルチスレッドアプリケーションを作成することが非常に難しい理由です。
分かりますか、 __sync_fetch_and_add
確かにアトミックですが、通常の関数のように動作します-したがって、「num」の現在の値をパラメーターとして受け取ります。関数の原子性が壊れていると言うのはまったく正しくありません-num
から値をロードするのは呼び出し側の責任であり、関数のインターフェイスの一部ではないためです。これについても同様に文句を言うことができます。
__sync_fetch_and_add(&var, some_really_long_function());
さらに悪いことに
__sync_fetch_and_add(long_function_1(), long_function_2());
「と解釈されるかもしれない」とあなたは言う
しかし、C仕様によると、それはmayがこのように解釈されるのではなく、むしろmustがこのように解釈されます。それ以外の場合、コンパイラは適合しません(実際には、#1と#2を入れ替えることができますが、ここでは重要ではありません)。