原子设置变量而不先进行比较

时间:2013-03-09 10:37:49

标签: atomic cas

我一直在阅读并尝试使用原子内存访问进行同步,主要用于教育目的。具体来说,我正在研究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,他们似乎也错过了这个功能,这让我相信它有充分的理由,而我的困惑只是基于缺乏知识。如果有人能够启发我,我会很感激。

1 个答案:

答案 0 :(得分:2)

我认为您必须检查OSAtomicCompareAndSwapInt结果,以确保实际设置了int