我一直在阅读并尝试原子内存访问以进行同步,主要用于教育目的。具体来说,我正在研究 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 中的比较成功,另一个线程 Y 也可以在 X 有机会更改变量之前先进入设置变量。
我知道在这个简单的示例中,我可以(并且应该!)简单地使用OSAtomicAdd32
,在这种情况下代码可以工作。但是,例如,如果我想以原子方式设置一个指针,使其指向另一个线程可以使用的新对象,该怎么办?
我查看了其他 API,它们似乎也缺少此功能,这使我相信这是有充分理由的,而我的困惑只是基于缺乏知识。如果有人可以启发我,我将不胜感激。