C# での操作がアトミックかどうかを知る体系的な方法はありますか? または、一般的なガイドラインや経験則はありますか?
3 に答える
より完全/詳細なものについて:
32ビット値型への読み取りと書き込みはアトミックです。これには、次の組み込み値(構造体)型が含まれますbool, char, byte, sbyte, short, ushort, int, uint, float
。次のタイプ(とりわけ)は、アトミックであることが保証されていませんdecimal, double, long, ulong
。
例えば
int x;
x = 10; // atomic
decimal d;
d = 10m; // not atomic
参照の割り当ても不可分操作です。
private String _text;
public void Method(String text)
{
_text = text; // atomic
}
はい。CLI 仕様を読みます: http://www.ecma-international.org/publications/standards/Ecma-335.htm。例えば:
I.12.6.6 アトミックな読み取りと書き込み
適合する CLI は、ある場所へのすべての書き込みアクセスがある場合、ネイティブ ワード サイズ (ネイティブ int 型のサイズ) を超えない適切に配置されたメモリ位置への読み取りおよび書き込みアクセスがアトミックであることを保証するものとします (§I.12.6.2 を参照)。同じサイズ。アトミック書き込みは、書き込まれたビット以外のビットを変更してはなりません。明示的なレイアウト制御 (パーティション II (インスタンス レイアウトの制御) を参照) を使用してデフォルトの動作を変更しない限り、自然なワード サイズ (ネイティブ int のサイズ) を超えないデータ要素は適切に配置されます。オブジェクト参照は、ネイティブ ワード サイズで格納されているかのように扱われます。
[注: クラス ライブラリの一部としてその目的で提供されるメソッドを除いて、メモリのアトミック更新 (読み取り-変更-書き込み) についての保証はありません (パーティション IV を参照)。小さなデータ項目への直接書き込みをサポートしていないハードウェアでアトミックな読み取り/変更/書き込みを行うには、「小さなデータ項目」(ネイティブ ワード サイズ以下の項目) のアトミック書き込みが必要です。エンドノート】
[注: ネイティブ int のサイズが 32 ビットの場合、8 バイト境界でデータが整列されている場合に一部の実装でアトミック操作が実行される場合でも、8 バイト データへのアトミック アクセスは保証されません。エンドノート】
64 ビット長の質問については、Eric Lippert がここで回答しています: https://ericlippert.com/2011/05/31/atomicity-volatility-and-immutability-are-different-part-two/
CLI 仕様は、実際にはより強力な保証を行っています。CLI は、プロセッサの自然なポインター サイズ (またはそれより小さいサイズ) の値型の変数の読み取りと書き込みがアトミックであることを保証します。CLR の 64 ビット バージョンの 64 ビット オペレーティング システムで C# コードを実行している場合、64 ビットの double と long integer の読み取りと書き込みもアトミックであることが保証されます。C# 言語では保証されていませんが、ランタイム仕様では保証されています。(CLI の実装によって実装されていない環境で C# コードを実行している場合、もちろんその保証に頼ることはできません。提供される保証を知りたい場合は、ランタイムを販売したベンダーにお問い合わせください。)
アトミック アクセスに関するもう 1 つの微妙な点は、読み取りまたは書き込み対象の変数が、メモリ内の正しい位置に配置されたストレージに関連付けられている場合にのみ、基盤となるプロセッサがアトミック性を保証することです。最終的に、変数はどこかのメモリへのポインタとして実装されます。32 ビット オペレーティング システムでは、読み取りまたは書き込みがアトミックであることを保証するために、そのポインターは 4 で割り切れる必要があり、64 ビット オペレーティング システムでは 8 で割り切れる必要があります。
ここで取得できる CLI 仕様から:
「適合する CLI は、ネイティブ ワード サイズ (ネイティブ int 型のサイズ) を超えない適切に配置されたメモリ位置への読み取りおよび書き込みアクセスがアトミックであることを保証する必要があります…」</p>
ここのC#仕様のセクション12.5 :
「次のデータ型の読み取りと書き込みはアトミックでなければなりません: bool、char、byte、sbyte、short、ushort、uint、int、float、および参照型。」また、「…インクリメントまたはデクリメントの場合のように、アトミックな読み取り-変更-書き込みの保証はありません。」</p>
これでインクリメント操作をアトミックにします。