|
普通に 32bit CPU で 32bit 変数を扱う場合、読み込み操作と書込み操作は atomic だ。 (適切に align されている場合に限定)
・ VC++ において long は 32bit だから long x; があるとして ・ C# の int は 32bit だから int x; があるとして x=1; で行われる書込み操作は atomic std::cout << x; / Console.WriteLine(x); で行われる読み込み操作は atomic 機械語レベルで1命令なので (mov [x], eax など)
++x; では 読み込み→加工→書き込み なので non atomic x を複数スレッドで同時アクセスしているとかならロック操作が必要 だから InterlockedIncrement みたいな機能が用意されている。
y=x; では x を読み込む→別スレッドで x が更新される→自スレッドで y を書き込む なので 全操作は atomic だが y が更新されるとき x の値はもう違うかもしれない
32bit CPU で 64bit 変数を扱う場合は単純読み込み、単純書き込みに見えても non-atomic VC++ の long long や C# の long は 64bit だから単純操作も non-atomic なので 64bit 変数の atomic 性質を 32bit 環境で保証したかったらロックが必要 # スレッド間で 64bit 変数を共有しないほうがいい、ってことだ
機械語レベルで複数命令なので mov [x].hi, 0 ここで他スレッド等が x に干渉 mov [x].lo, 1
C/C++ のビットフィールドも Read/Modify/Write になるので non-atomic
|