我一直在阅读并尝试使用原子内存访问进行同步,主要用于教育目的。具体来说,我正在研究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,他们似乎也错过了这个功能,这让我相信它有充分的理由,而我的困惑只是基于缺乏知识。如果有人能够启发我,我会很感激。
答案 0 :(得分:2)
我认为您必须检查OSAtomicCompareAndSwapInt
结果,以确保实际设置了int
。