我尝试编写一个物理模拟程序。我使用两个线程,一个用于计算,一个用于gui。为了在它们之间交换数据,我使用了结构
struct sim_data {
int running;
int steps;
int progress;
...
};
并将其包含在不同的帖子中
void *sim(void *args) {
struct sim_data *my_data;
my_data=(struct sim_data *)args;
...
}
按
设置值时my_data->progress=1000;
数据在同一个线程中可用,但在第二个线程中不可靠。我想在启动程序时可能会有10%的机会在第二个线程中读取不同的值,然后在第一个线程中写入。虽然数据是循环写入的,但我不认为这是一个时间问题。
我觉得这很奇怪。有什么猜测出了什么问题?
答案 0 :(得分:1)
C ++ 11规范声明数据竞争情况是在一个线程写入某个位置而第二个线程可以读取或写入该位置的任何时候。它声明在发生这种情况时会出现未定义的行为。在您的情况下,一个线程正在写入my_data->进度而另一个正在读取它。
解决方案是使用同步,例如原子注入或锁定。
C ++编译器进行了非常令人印象深刻的优化,使您的单线程程序运行得更快。例如,它可能证明,在单线程世界中,没有办法看到1000值,只是选择不打印它。
还有更多丑陋的案件是合法的。如果编译器知道你想要存储1000,它可能会选择不存储任何东西,而是使用该存储器作为空间将临时结果“溢出”到它而不是分配更多空间,然后最终存储1000。平均时间,您可以阅读任意值。
对此问题采取相当幽默的观点:http://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong
答案 1 :(得分:0)
最简单的解决方案:
struct sim_data {
int running;
int steps;
atomic<int> progress; //this will guarantee the data are coherent between two threads
...
};