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

Han*_*ank 10 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;
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*Ben 6

您应该使用GCC内置函数,而不是(见.)这工作得很好,而且还与国际刑事法院.

int a; 
__sync_fetch_and_add(&a, 1); // atomic a++
Run Code Online (Sandbox Code Playgroud)

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


pax*_*blo 3

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

如果没有这一点,汇编代码输出就没有前缀lock,您会发现内核相互干扰。

但无论如何我都会使用 pthread 函数,因为它们可以跨更多平台移植。

  • 谢谢。我在 gcc -E 输出中发现没有锁定前缀。只需在包含 &lt;atomic.h&gt; 之前添加 #define CONFIG_SMP 即可。实际上这段代码用于测试不同线程安全增量方法的效率。它不是用于生产的。:-) (4认同)