当只有一个线程写入c ++中的bool变量时,是否存在竞争条件?

时间:2014-01-17 10:16:15

标签: c++ multithreading synchronization race-condition

在下面的代码示例中,程序执行永远不会结束。

它会创建一个线程,在终止之前等待全局bool设置为true。只有一位作家和一位读者。我相信允许循环继续运行的唯一情况是bool变量是否为假。

bool变量如何可能与只有一个作者的状态不一致?

#include <iostream>
#include <pthread.h>
#include <unistd.h>

bool done = false;

void * threadfunc1(void *) {
    std::cout << "t1:start" << std::endl;
    while(!done);
    std::cout << "t1:done" << std::endl;

    return NULL;
}

int main()
{
    pthread_t threads;

    pthread_create(&threads, NULL, threadfunc1, NULL);

    sleep(1);

    done = true;
    std::cout << "done set to true" << std::endl;

    pthread_exit(NULL);

    return 0;
}

6 个答案:

答案 0 :(得分:7)

threadfunc1()

中的这个陈述有一个问题
   while(!done);

可以由编译器实现,如:

       a_register = done;
   label:
       if (a_register == 0) goto label;

因此永远不会看到done的更新。

答案 1 :(得分:3)

实际上并没有什么能阻止编译器优化while循环。使用atomic或mutex从多个线程访问bool。这是唯一受支持且正确的解决方案。当您使用posix时,在这种情况下,互斥锁将是正确的解决方案。

不要使用volatile。有一个posix标准说明了什么必须起作用,volatile不是一个有保证工作的解决方案。

还有一个问题:在将标志设置为false之前,没有保证新创建的线程每次都开始运行。

答案 2 :(得分:1)

竞争条件是指:当两个线程访问同一个对象时,其中至少有一个是写入。

这意味着您将有两种类型的赛车,写 - 写冲突和写 - 读冲突。

回到你的代码,你基本上有两个线程,一个是主线程,另一个是你用pthread_create创建的。

其中一个是读:while(!done),其中一个是write:done = true。

你肯定有竞争条件。

答案 3 :(得分:0)

  

当只有一个线程写入c ++中的bool变量时,是否存在竞争条件?

是。在您的情况下,主线程也是一个线程(即您有一个线程写入和一个线程读取)。

  

bool变量如何可能只与一个编写器一起处于不一致状态?

编译器(应该是)优化编译器。它可能会优化完成变量的读取,除非你注意避免这种情况(改为使用std::atomic<bool> done)。

答案 4 :(得分:0)

不保证对一个字节的bool的赋值是原子的

答案 5 :(得分:0)

对于这样简单的例子,volatile就足够了。但对于绝大多数现实世界的情况来说并非如此。使用条件变量执行此任务。乍一看它们看起来很奇怪但实际上它们很合乎逻辑。在x86 bool IS原子上读/写(对于ARM,可能不是)。矢量还有一个障碍:它不是bool的矢量,它是一个位域。要从几个线程写入向量,请使用vector(或bool arr [SIZE])。 你也不加入线程,这是错误的。