【问题标题】:Operations from atomic.h seem to be non-atomicatomic.h 中的操作似乎是非原子的
【发布时间】:2009-05-04 08:28:44
【问题描述】:

以下代码为 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;
}

【问题讨论】:

  • 我没有答案,但我想说:感谢您用完整的工作源代码提出一个措辞清晰、明确的问题。我希望每个人都这样做!

标签: c linux multithreading


【解决方案1】:

您应该改用 gcc 内置函数(请参阅。this)这很好用,也适用于 icc。

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

请注意,当您在未锁定的情况下修改变量时,您应该注意缓存一致性问题。

【讨论】:

    【解决方案2】:

    This old post 暗示

    • 不应该在用户空间程序中包含这个内核头文件
    • 众所周知,它无法为用户空间程序提供原子性。

    所以...也许这就是您看到问题的原因?

    【讨论】:

    • 感谢您的信息。我只是想知道为什么 linux 内核不将这些有用的原语暴露给用户态程序。它们比 pthread_mutex 方法更轻量级和更高效。
    • @hank,好吧,内核确实如此。它的 glibc 让人困惑。
    • @Hank:嗯,因为它们不起作用。原子操作在某些平台上需要特权操作,这必须与内核和用户空间完全不同。
    • @TimPost:它只是指出标题不受#ifdef __KERNEL__ 保护。但它们不适用于许多平台。
    【解决方案3】:

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

    否则,汇编代码输出没有lock 前缀,您会发现您的内核相互干扰。

    但我还是会使用 pthread 函数,因为它们可以跨更多平台移植。

    【讨论】:

    • 谢谢。我在 gcc -E 输出中发现没有锁定前缀。只需在包含 之前添加#define CONFIG_SMP 即可。实际上,这段代码用于测试不同线程安全增量方法的效率。这不是为了生产。 :-)
    【解决方案4】:

    Linux 内核 atomic.h 不能从用户空间使用,而且从来没有。在 x86 上,其中一些可能会起作用,因为 x86 是相当同步友好的架构,但在某些平台上,它严重依赖能够执行特权操作(旧版 arm)或至少能够禁用抢占(旧版 arm 和 sparc至少),在用户空间中不是这样!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-10
      • 2016-11-05
      相关资源
      最近更新 更多