C++ 如果一个线程写入后切换一个布尔值,那么在另一个线程的循环中读取该布尔值是否安全?
C++ if one thread writes toggles a bool once done, is it safe to read that bool in a loop in a single other thread?
我正在构建一个非常简单的程序作为练习。
这个想法是通过递归遍历目录的所有内容,并对目录(及其子目录)中包含的所有文件的大小求和来计算目录的总大小。
为了向用户显示程序仍在运行,此计算在另一个线程上执行,而主线程每秒打印一个点 .
。
现在主线程当然需要知道什么时候应该停止打印点并且可以查询结果。
可以使用例如a std::atomic<bool> done(false);
并将其传递给将执行计算的线程,该线程将在完成后将其设置为 true
。但是我想知道在这种简单的情况下(一个线程一旦完成写入,一个线程定期读取直到非零)是否有必要为此使用原子数据类型。显然,如果 多个 线程可能写入它,则需要对其进行保护。但在这种情况下,只有一个写入线程和一个读取线程。
这里是否有必要使用原子数据类型,或者是否过度使用普通数据类型?
是的,有必要。
问题是处理器的不同内核对 "same" 数据有不同的看法,特别是 CPU 中缓存的数据。 atomic
部分确保正确刷新这些缓存,以便您可以安全地执行您正在尝试执行的操作。
否则,另一个线程很可能永远不会真正看到第一个线程的标志更改。
是的,有必要。否则不能保证在一个线程中对 bool
的更改将在另一个线程中被观察到。事实上,如果编译器发现 bool
变量显然没有在设置它的执行线程中再次使用,它可能会完全优化掉设置 bool
值的代码。
是的,有必要。规则是,如果两个线程可能同时访问同一内存,并且至少有一个线程是写入器,那么就会发生数据竞争。任何具有数据竞争的程序的执行都具有未定义的行为。
C++14标准的相关引述:
1.10/23
The execution of a program contains a data race if it contains two potentially concurrent conflicting actions, at least one of which is not atomic, and neither happens before the other, except for the special case for signal handlers described below. Any such data race results in undefined behavior.
1.10/6
Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.
我正在构建一个非常简单的程序作为练习。
这个想法是通过递归遍历目录的所有内容,并对目录(及其子目录)中包含的所有文件的大小求和来计算目录的总大小。
为了向用户显示程序仍在运行,此计算在另一个线程上执行,而主线程每秒打印一个点 .
。
现在主线程当然需要知道什么时候应该停止打印点并且可以查询结果。
可以使用例如a std::atomic<bool> done(false);
并将其传递给将执行计算的线程,该线程将在完成后将其设置为 true
。但是我想知道在这种简单的情况下(一个线程一旦完成写入,一个线程定期读取直到非零)是否有必要为此使用原子数据类型。显然,如果 多个 线程可能写入它,则需要对其进行保护。但在这种情况下,只有一个写入线程和一个读取线程。
这里是否有必要使用原子数据类型,或者是否过度使用普通数据类型?
是的,有必要。
问题是处理器的不同内核对 "same" 数据有不同的看法,特别是 CPU 中缓存的数据。 atomic
部分确保正确刷新这些缓存,以便您可以安全地执行您正在尝试执行的操作。
否则,另一个线程很可能永远不会真正看到第一个线程的标志更改。
是的,有必要。否则不能保证在一个线程中对 bool
的更改将在另一个线程中被观察到。事实上,如果编译器发现 bool
变量显然没有在设置它的执行线程中再次使用,它可能会完全优化掉设置 bool
值的代码。
是的,有必要。规则是,如果两个线程可能同时访问同一内存,并且至少有一个线程是写入器,那么就会发生数据竞争。任何具有数据竞争的程序的执行都具有未定义的行为。
C++14标准的相关引述:
1.10/23
The execution of a program contains a data race if it contains two potentially concurrent conflicting actions, at least one of which is not atomic, and neither happens before the other, except for the special case for signal handlers described below. Any such data race results in undefined behavior.
1.10/6
Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.