我正在构建一个非常简单的程序作为练习。
这个想法是通过递归迭代其所有内容来计算目录的总大小,并总结目录(及其子目录)中包含的所有文件的大小。
要向用户显示程序仍在工作,此计算在另一个线程上执行,而主线程每秒打印一次点.
。
现在主线程当然需要知道什么时候应该停止打印点并且可以查找结果。
可以使用例如a std::atomic<bool> done(false);
并将其传递给将执行计算的线程,一旦完成,它将设置为true
。但我想知道在这个简单的情况下(一个线程写完一次,一个线程周期性地读取直到非零),有必要使用原子数据类型。显然,如果多个线程可能写入它,则需要对其进行保护。但在这种情况下,只有一个写作线程和一个阅读线程。
是否有必要在此处使用原子数据类型,或者它是否过度,是否可以使用普通数据类型?
答案 0 :(得分:3)
是的,这是必要的。
问题在于处理器的不同内核可以具有“相同”数据的不同视图,特别是在CPU内缓存的数据。 atomic
部分确保正确刷新这些缓存,以便您可以安全地执行您要执行的操作。
否则,其他线程很可能永远不会从第一个线程看到标志更改。
答案 1 :(得分:2)
是的,这是必要的。否则,无法保证在另一个线程中可以观察到对一个线程中的bool
的更改。实际上,如果编译器发现bool
变量显然没有在设置它的执行线程中再次使用,它可能会完全优化掉设置bool
值的代码。
答案 2 :(得分:2)
是的,这是必要的。规则是如果两个线程可能同时访问同一个内存,并且至少有一个线程是编写器,那么您就有数据竞争。任何执行数据竞争的程序都有不确定的行为。
C ++ 14标准的相关引用:
1.10 / 23
程序的执行包含数据竞争,如果它包含两个可能同时发生冲突的动作,其中至少有一个不是原子的,并且除了下面描述的信号处理程序的特殊情况之外,它们都不会发生在另一个之前。任何此类数据竞争都会导致未定义的行为。
1.10 / 6
如果其中一个修改内存位置(1.7)而另一个访问或修改相同的内存位置,则两个表达式评估会发生冲突。