データレースを含むプログラムの実装制限

データレースを含むプログラムの実装制限

前のセクションでは、データレースフリープログラム実行の正式な定義を示しました。このセクションでは、実際にレースを含むプログラムに対して実装が提供しなければならないセマンティクスについて、非公式に説明します。

任意の実装は、データレースを検出すると、レースを報告してプログラムの実行を停止することができます。ThreadSanitizer を使用する実装(go build -race でアクセス)は、まさにこれを行います。

配列、構造体、または複素数の読み取りは、個々のサブ値(配列要素、構造体フィールド、または実数/虚数成分)の読み取りとして、任意の順序で実装される場合があります。同様に、配列、構造体、または複素数の書き込みは、個々のサブ値の書き込みとして、任意の順序で実装される場合があります。

メモリ位置 x にマシンワード以下のサイズの値を持つ位置の読み取り r は、rw の前に事前発生しない w と、ww’ の前に事前発生し、w’r の前に事前発生する書き込み w’ が存在しないような書き込み w を観測しなければなりません。つまり、各読み取りは、先行するまたは並行する書き込みによって書き込まれた値を観測しなければなりません。

さらに、因果関係のない「薄い空気からの」書き込みの観測は許可されません。

単一のマシンワードより大きなメモリ位置の読み取りは、ワードサイズのメモリ位置と同じセマンティクスを満たすことが推奨されますが、必須ではありません。パフォーマンス上の理由から、実装は代わりに、より大きな操作を、未指定の順序での個々のマシンワードサイズの操作の集合として扱うことがあります。これは、複数ワードデータ構造でのレースが、単一の書き込みに対応しない一貫性のない値につながる可能性があることを意味します。値が内部の(ポインタ、長さ)または(ポインタ、型)ペアの一貫性に依存する場合、これはほとんどの Go 実装でのインターフェース値、マップ、スライス、文字列の場合であり、そのようなレースは任意のメモリ破損につながる可能性があります。

不正な同期の例は、以下の「不正な同期」セクションで示されています。

実装の制限の例は、以下の「不正なコンパイル」セクションで示されています。