在下面的代码示例中,程序执行永远不会结束。
它会创建一个线程,在终止之前等待全局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;
}
答案 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])。 你也不加入线程,这是错误的。