multithreading - 多线程代码中是否有必要使用原子标志?
问题描述
我想知道是否真的有必要在多线程代码中使用原子标志。对于这个问题,我关注多线程代码中的一个常见情况:通过设置标志来停止线程。
让我们假设以下伪代码:
is_running = 1;
create_threads(stopper_thread, running_thread_A, running_thread_B, running_thread_C);
stopper_thread running_thread_A running_thread_B running_thread_C
-------------------------------------------------------------------------------------------
if (x) | while(is_running) { | while(is_running) { | while(is_running) {
is_running = 0; | } | } | }
在这个伪代码中,所有running_thread_x
线程都使用公共变量is_running
来检查它们是否正在运行。当我们想阻止他们时stopper_thread
,我们只是设置is_running
为0
。这意味着这is_running
是线程之间的共享资源。在许多编码示例中,人们使用原子变量(例如std::atomic_flag
在 C++ 中)来is_running
标记或访问临界区中的该变量,以在访问该变量时提供互斥。
但是同步这个标志有必要吗?
我以某种方式相信,在类似于上述示例的情况下,仅作为单个或多个停止线程停止操作,实际上没有必要同步对该标志的访问。
为什么?
因为据我所知,即使我们is_running
在要停止线程时可以同时访问多个线程中的标志,这种访问也不会阻止通过停止线程设置1
此0
标志。发生的情况是,这种变化可能不会立即反映在正在运行的线程中。但这重要吗?我认为不会,因为如果我们不0
从is_running
当前正在运行的线程迭代中读取值,您最终会在多次迭代后读取它,并且线程最终将停止。所以设置这个标志最终会停止所有正在运行的线程,但停止可能会延迟一点。
你怎么看我的论点?我的论点正确吗?或者我可能错过了我的论点失败的情况?
解决方案
当std::mutex
/pthread_mutex_t
和std::condition_variable
/pthread_cond_t
用于与线程通信时,标志不应该是原子的,因为它必须仅在互斥锁被锁定时存储和加载。尝试使用std::atomic
//为标志绕过互斥锁会导致死锁atomic_flag
。atomic_bool
例如:
+-----+--------------------------------+--------------------------------+
|Step |Thread A |Thread B |
+-----+--------------------------------+--------------------------------+
|1 | |lock the mutex |
+-----+--------------------------------+--------------------------------+
|2 | |check whether the flag is not |
| | |set or the queue is empty |
+-----+--------------------------------+--------------------------------+
|3 |set the atomic flag | |
+-----+--------------------------------+--------------------------------+
|4 |notify condition variable |<notification is lost> |
+-----+--------------------------------+--------------------------------+
|5 | |and if so wait on the condition |
| | |variable. |
+-----+--------------------------------+--------------------------------+
在这种情况下,线程 A 可以在 B 完成步骤 2 之后但在完成步骤 5 之前执行步骤 3 和 4。在这种情况下,来自步骤 4 的条件变量通知丢失,导致线程 B 永远等待步骤 5 中的条件变量。
推荐阅读
- firebase - 如何使用expo将图像上传到firebase?
- sql-server - SQL Server 中的 SSIS 列映射问题
- php - 构造函数注入 vs setter 工厂
- video - 取消暂停后如何检测 MediaStreamTrack 是否有“真实”数据?
- python-3.x - 混淆矩阵错误:实际值和预测值之间的数据类型不匹配
- angular - 类型与 Firestore 观察者不匹配
- pandas - Python将值从DataFrame传递到另一个
- sql - 所有迁移工作不正常
- node.js - 删除命令后,MS Teams Bot 继续显示命令
- javascript - JavaScript 验证选择框