c - 如何使用不同的线程使用openmp安全地更新C结构

标签 c multithreading parallel-processing thread-safety openmp

我正在写一个 randomAnimalGenerator。它是一个多线程C程序,使用VS2010,适用于Windows X64,将用于为动物园随机生成动物。

我怎样才能让不同的线程都安全地写入全局结构(“zoo”)的成员,而不用对 zoo 结构实现锁定?这 全局结构的值将始终只会递增 (++),而不会递减 (--)。在下面的代码中,在不使用 OMP 的情况下,狮子、老虎和熊各自的正确值为 45,000。但是使用并行循环,值不等于 45,000。

有没有办法让 Openmp 将这些写入调度到同一个变量,而不会弄乱制作结构的私有(private)版本?

#define LIONS 1
#define TIGERS 2
#define BEARS 3

// global struct
struct 
{
    int lions;
    int tigers;
    int bears;
} zoo;


void addAnimalsToZoo(void)
{
    int animalType = randomAnimalGenerator();

    if (animalType == LION)
        ++zoo.lions;
    else
    if (animalType == TIGER)
        ++zoo.tigers;
    else
    if (animalType == BEAR)
        ++zoo.bears;
    else
        printf("unknown animal type generated\n");
}


void myZooMaker(void)
{

    #pragma omp parallel for
    for (int i = 0; i < 45000; ++i)
        addAnimalsToZoo();
}

最佳答案

如果不进行重大重构,您的程序将无法正常运行。如前所述,该程序展示了规范的数据竞争,多个线程在没有协调的情况下同时更新共享数据结构。

你可以:

  1. 从结构中删除变量 lionstigersbears(稍后我会解释原因)。
  2. 修改 randomAnimalGenerator 以适当的概率返回其中一只动物。

然后,这是近似值,因为我不是 C 程序员,按照这些行重写

int lions;
int tigers;
int bears;

lions = 0;
tigers = 0;
bears = 0;

#pragma omp parallel for default(shared) private(i) reduction(+:lions, +:tigers, +:bears)
for (int i = 0; i < 45000; ++i)
{
    int newAnimal;
    newAnimal = randomAnimalGenerator();
    if (newAnimal==LION) ++lions;
    if (newAnimal==TIGER) ++tigers;
    if (newAnimal==BEAR) ++bears;
}

最后,变量 lionstigersbears 的总和应为 45000。请注意减少子句的使用和默认可访问性声明为 shared。 OpenMP 缩减不能应用于结构的元素或整个结构,这就是我放弃 zoo 的原因。

我不保证代码是正确的,但你应该明白了。

关于c - 如何使用不同的线程使用openmp安全地更新C结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20407226/

相关文章:

java - 示例 SyncService 中 sSyncAdapterLock 的用途是什么?

c++ - 我是否需要保护一个由一个线程写入并由多个线程读取的变量?

java - Selenium 和 JUnit 在多个驱动程序中并行执行测试方法

c# - 后台线程/进程

c - 双指针的memset操作

c - kernel hashtable.h 哈希表的动态大小

c++ - 我的任务是将 lwIP 从 C 转换为 C++

bash - 并行运行 bash 脚本

r - 有没有另一种方法可以在 worker 中加载额外的包(并行计算)?

c - 错误 : expected '=' , ','、 ';'、 'asm' 或 '__attribute__' 之前的 'int'