などのpthread_create()
関数は外部関数であるため、コンパイラは、関数を呼び出す前に、外部関数に表示される可能性のある副作用 (グローバル変数への書き込みなど) を確実に実行する必要があります。コンパイルはa
、最初のケースの関数呼び出しの後まで書き込みを並べ替えることができませんでした)a
グローバルであるか、そうでなければ外部からアクセスできる可能性があると仮定します)。
これはどの C コンパイラにも必要な動作であり、実際にはスレッドとはほとんど関係ありません。
ただし、変数がローカル変数である場合、アドレスのようなものが取得されて外部で利用可能にされない限りa
、コンパイラは関数呼び出しの後までそれを並べ替えることができる可能性があります (a
そのことについてはメモリ内にまったく収まらない可能性があります)。a
どういうわけか(スレッドパラメーターとして渡すなど)。
例えば:
int a;
void foo(void)
{
a = 1;
pthread_create(...); // the compiler can't reorder the write to `a` past
// the call to `pthread_create()`
// ...
}
void bar(void)
{
int b;
b = 1;
pthread_create(...); // `b` can be initialized after calling `pthread_create()`
// `b` might not ever even exist except as a something
// passed on the stack or in a register to `printf()`
printf( "%d\n", b);
}
これをより詳細に概説しているドキュメントがあるかどうかはわかりません - これは主に C の 'as if' ルールでカバーされています。5.1.2.3/3「プログラムの実行」にあるC99では。Cは、副作用が完全でなければならないシーケンスポイントを持つ抽象マシンによって指定され、プログラムは、副作用が必要ないとコンパイラーが推測できる場合を除いて、その抽象マシンモデルに従う必要があります。
上記の私の例では、コンパイラは通常、 が設定を必要としないfoo()
ことを推測できないため、 を呼び出す前に値への設定の副作用を完了する必要があります。他の場所で使用されていないと推測できるグローバルな最適化を実行するコンパイラがある場合、それらは割り当てを遅らせたり省略したりする可能性があることに注意してください。ただし、その場合、他に副作用を使用しているものは何もないため、問題はありません。a = 1;
pthread_create()
a
1
pthread_create()
a