Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;如果一个线程写入一个bool,那么在另一个线程的循环中读取该bool是否安全?_C++_Multithreading_Atomicity - Fatal编程技术网

C++ C++;如果一个线程写入一个bool,那么在另一个线程的循环中读取该bool是否安全?

C++ C++;如果一个线程写入一个bool,那么在另一个线程的循环中读取该bool是否安全?,c++,multithreading,atomicity,C++,Multithreading,Atomicity,我正在构建一个非常简单的程序作为练习 其思想是通过递归迭代目录的所有内容,并将目录(及其子目录)中包含的所有文件的大小相加,来计算目录的总大小 为了向用户显示程序仍在工作,此计算在另一个线程上执行,而主线程每秒打印一次点 现在,主线程当然需要知道何时停止打印点,并可以查找结果。 可以使用例如astd::atomic done(false)并将其传递给将执行计算的线程,一旦计算完成,该线程将将其设置为true。但我想知道在这个简单的情况下(一个线程完成写入,一个线程周期性读取,直到非零),是否有必

我正在构建一个非常简单的程序作为练习

其思想是通过递归迭代目录的所有内容,并将目录(及其子目录)中包含的所有文件的大小相加,来计算目录的总大小

为了向用户显示程序仍在工作,此计算在另一个线程上执行,而主线程每秒打印一次点

现在,主线程当然需要知道何时停止打印点,并可以查找结果。 可以使用例如a
std::atomic done(false)
并将其传递给将执行计算的线程,一旦计算完成,该线程将将其设置为
true
。但我想知道在这个简单的情况下(一个线程完成写入,一个线程周期性读取,直到非零),是否有必要为此使用原子数据类型。显然,如果多个线程可能会对其进行写入,则需要对其进行保护。但在这种情况下,只有一个写线程和一个读线程

是否有必要在此处使用原子数据类型,或者它是否过于苛刻,是否可以使用普通数据类型来代替?

是的,这是必要的

问题在于,处理器的不同内核可以对“相同”数据有不同的视图,尤其是缓存在CPU中的数据。原子的
部分确保正确地刷新这些缓存,以便您可以安全地执行您试图执行的操作


否则,另一个线程很可能永远看不到第一个线程的标志更改。

是的,这是必要的。否则,不能保证在一个线程中对
bool
的更改在另一个线程中是可见的。事实上,如果编译器发现
bool
变量显然从未在设置它的执行线程中再次使用,那么它可能会完全优化掉设置
bool
值的代码。是的,这是必要的。规则是,如果两个线程可能同时访问同一内存,并且至少有一个线程是写入程序,那么就存在数据竞争。具有数据竞争的程序的任何执行都具有未定义的行为

C++14标准的相关引用:

1.10/23

如果一个程序的执行包含两个潜在的并发冲突动作,则该程序的执行包含一个数据竞争,其中至少一个动作不是原子的,并且两个动作都不在另一个动作之前发生,下面描述的信号处理程序的特殊情况除外。任何这样的数据竞争都会导致未定义的行为

1.10/6

如果其中一个修改内存位置(1.7),而另一个访问或修改同一内存位置,则两个表达式求值会发生冲突


如果bool标记为
volatile
,编译器将无法优化任何访问。因此,即使我将bool作为引用传递给线程,编译器也可能会将我的代码重写为永远不会看到值更改的内容?如果编译器看到bool值设置后,执行线程再也不会使用它,编译器可以合法地优化整件事。在早些时候,执行线程构造了一个名为
std::thread
的类的实例,并向该bool传递引用或指针,这一事实并没有改变。C++编译器不知道构造一个类的例子,称为<代码>:ST::线程< /COD>最终创建一个新的执行线程。这是C++库的函数。@ CAPTAIGIRAFEFE不同于你链接的问题的ASKER。我没有误解volatile的功能。我不是说访问不需要同步,我是说编译器不会对
volatile
对象执行有问题的优化。@StoryTeller-但这没有帮助<代码>易失性
与线程无关,它与内存映射硬件有关。如果线程在单独的CPU上运行,它们可能看不到彼此的
volatile
变量,即使读写是由硬件执行的。对于原子,它们是这样做的。我希望原语
int
bool
的写入/读取是原子的。为什么不是这样?(或者它是“不能假定为”的东西之一?)无论如何,感谢您引用本标准的相关章节。这是迄今为止最清楚的答案:-)。@Qqwy:我认为创建原子对象的唯一标准方法是声明它具有类型
std::atomic
std::atomic_标志