来自atomic.h的操作似乎是非原子的

时间:2009-05-04 08:28:45

标签: c linux multithreading

以下代码为n和v生成随机值。在没有得到适当保护的情况下,n是随机的并不奇怪。但是假设v应该最终为0.我的代码中有什么问题吗?或者有人能为我解释一下吗?感谢。

我正在研究x86架构的4核服务器。 uname如下。

Linux 2.6.9-22.ELsmp#1 SMP Mon Sep 19 18:00:54 EDT 2005 x86_64 x86_64 x86_64 GNU / Linux

#include <stdio.h>
#include <pthread.h>
#include <asm-x86_64/atomic.h>

int n = 0;
atomic_t v;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

#define LOOP 10000

void* foo(void *p)
{
    int i = 0;
    for(i = 0; i < LOOP; i++) {
//        pthread_mutex_lock(&mutex);
        ++n;
        --n;
        atomic_inc(&v);
        atomic_dec(&v);
//        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

#define COUNT 50

int main(int argc, char **argv)
{
    int i;
    pthread_t pids[COUNT];
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    atomic_set(&v, 0);

    for(i = 0; i < COUNT; i++) {
        pthread_create(&pids[i], &attr, foo, NULL);
    }

    for(i = 0; i < COUNT; i++) {
        pthread_join(pids[i], NULL);
    }

    printf("%d\n", n);
    printf("%d\n", v);
    return 0;
}

4 个答案:

答案 0 :(得分:6)

你应该使用gcc内置函数(参见。this)这很好用,也适用于icc。

int a; 
__sync_fetch_and_add(&a, 1); // atomic a++

请注意,在没有锁定的情况下修改变量时,应该了解缓存一致性问题。

答案 1 :(得分:4)

This old post暗示

  • 您应该在用户空间程序中包含此内核标头并不明显
  • 众所周知,它无法为用户空间程序提供原子性。

所以......也许这就是你遇到问题的原因?

答案 2 :(得分:3)

我们可以看一下代码的汇编输出(gcc -E,我认为)。甚至认为uname表明它是SMP感知的,这并不一定意味着它是用CONFIG_SMP编译的。

如果没有这个,汇编程序代码输出没有lock前缀,你可以发现你的核心相互干扰。

但是我会使用pthread功能,因为它们可以在更多平台上移植。

答案 3 :(得分:0)

Linux内核atomic.h在userland中无法使用,从来没有。在x86上,其中一些可能会起作用,因为x86是相当友好的体系结构,但在某些平台上,它很大程度上依赖于能够执行特权操作(较旧的臂)或至少能够禁用抢占(较旧的arm和sparc)至少),在userland中不是这样的情况!