私は、主に教育目的で、同期のためのアトミックメモリアクセスを読み、実験してきました。具体的には、Mac OS X のOSAtomic*
機能ファミリーに注目しています。ここに私が理解していないことがあります:変数を変更 (追加、インクリメントなど) する代わりに、変数をアトミックに設定する方法がないのはなぜですか? OSAtomicCompareAndSwap*
可能な限り近いですが、関数全体ではなく、スワップのみがアトミックです。これにより、次のようなコードが機能しなくなります。
const int N = 100000;
void* threadFunc(void *data) {
int *num = (int *)data;
// Wait for main thread to start us so all spawned threads start
// at the same time.
while (0 == num) { }
for (int i = 0; i < N; ++i) {
OSAtomicCompareAndSwapInt(*num, *num+1, num);
}
}
// called from main thread
void test() {
int num = 0;
pthread_t threads[5];
for (int i = 0; i < 5; ++i) {
pthread_create(&threads[i], NULL, threadFunc, &num);
}
num = 1;
for (int i = 0; i < 5; ++i) {
pthread_join(threads[i], NULL);
}
printf("final value: %d\n", num);
}
この例を実行すると、理想的には最終値として 500,001 が生成されます。ただし、そうではありません。スレッド X の OSAtomicCompareAndSwapInt での比較が成功した場合でも、X が変数を変更する前に、別のスレッド Y が最初に変数を設定する可能性があります。
この些細な例ではOSAtomicAdd32
、単純に を使用できる (そしてそうすべきです!) ことを認識しています。その場合、コードは機能します。しかし、たとえば、ポインターをアトミックに設定して、別のスレッドが操作できる新しいオブジェクトを指すようにしたい場合はどうでしょうか?
私は他の API を見てきましたが、それらにもこの機能が欠けているようです。これには正当な理由があり、私の混乱は知識不足に基づいているだけだと思います。誰かが私を啓発することができれば、私はそれを感謝します.