c - C 中的 volatile 是否安全/足够好,可以在没有共享数据时向另一个线程发出停止自身的信号?
问题描述
有许多资源可以解释为什么对于大多数多线程应用程序来说,单独使用 volatile 是不够的。
然而,仅仅用信号通知一个线程从另一个线程退出就足够了吗?在下面的示例中,主线程启动了第二个线程,一段时间后,它想要停止它。线程之间没有共享数据,也不需要线程返回代码,线程基本上只是用作附加硬件的保持活动触发器。
示例(为简洁起见省略了 thread_create 和 thread_join,它们基本上是 pthread_create 和 pthread_join 或 Windows 等效项的包装):
typedef struct {
volatile bool keepRunning;
} ThreadContext;
static void thread(void *arg) {
ThreadContext *context = (ThreadContext *)arg;
while (context->keepRunning) {
// do some fast operation
// ...
// then sleep before next iteration
msleep(100);
}
}
static int startThread(ThreadContext *context) {
context->keepRunning = true;
return thread_create(thread, context);
}
static void stopThread(ThreadContext *context) {
context->keepRunning = false;
thread_join();
}
static int main() {
ThreadContext context;
startThread(&context);
msleep(10000);
stopThread(&context);
}
编辑:我必须保持 Windows 兼容性并交叉编译到一些古老的工具链,所以 C11stdatomic.h
不适用。如果有办法在 Windows 上使用常规条件变量,这可能是我可以尝试检查我的所有目标是否支持它们的一种方式。
EDIT2:另外,在这种情况下,我不关心事件的精确顺序,线程应该只最终停止(最多几次迭代之后),而不是永远等待加入,但它不必在之后立即停止设置标志,即如果线程再进行几次迭代,它不会造成任何伤害。
解决方案
在大多数健全的架构和大多数健全的编译器上访问变量volatile bool
都可以。但是,标准不保证这一点。
volatile sig_atomic_t
POSIX 标准保证对异步中断类型的安全访问。为了安全使用volatile sig_atomic_t
。或者只是使用pthread_cond
.
typedef struct {
volatile sig_atomic_t keepRunning;
} ThreadContext;
在 C11 中,有一种方法可以检查访问bool
是否是原子的并且不受中断影响,如果ATOMIC_BOOL_LOCK_FREE
在stdatomic.h
.
一些参考资料:C11 草案 5.1.2.3p5和posix signal.h。
推荐阅读
- dataframe - 如何使用pyspark在每次迭代中将数据框结果保存在具有不同名称的配置单元表中
- outlook - 文本框中的用户表单 vlookup
- javascript - 让命运之轮停在 Angular 4 中的特定位置
- angular - TypeError:_this.handler.handle 不是函数
- oracle - Oracle 无效标识符(带内连接)
- vsto - 如何检测用户何时在 Outlook VSTO 中选择 NEW 或 OPEN 邮件
- mysql - MySql - 从具有大量连接表的主表中选择
- typescript - 如何使用父静态方法在 TypeScript 中创建子类?
- git - 使用提交 sha 过滤 gitlab 提交历史
- php - 删除 index.php 时出现 Codeigniter 错误 403