C中的volatile是否足够安全/良好,可以在没有共享数据时向另一个线程发出停止自身的信号?

C中的volatile是否足够安全/良好,可以在没有共享数据时向另一个线程发出停止自身的信号?,c,C,有许多参考资料解释了为什么对于大多数多线程应用程序来说,仅使用volatile是不够的 但是,它是否足够好,可以简单地向一个线程发送信号,让它退出另一个线程? 在下面的示例中,主线程启动第二个线程,一段时间后,它想要停止它。线程之间没有共享数据,也没有必要从线程返回代码,线程基本上只是用作连接硬件的保持活动触发器 示例(为了简洁起见,省略了thread_create和thread_join,它们基本上是pthread_create和pthread_join或Windows等效程序的包装): ty

有许多参考资料解释了为什么对于大多数多线程应用程序来说,仅使用volatile是不够的

但是,它是否足够好,可以简单地向一个线程发送信号,让它退出另一个线程? 在下面的示例中,主线程启动第二个线程,一段时间后,它想要停止它。线程之间没有共享数据,也没有必要从线程返回代码,线程基本上只是用作连接硬件的保持活动触发器

示例(为了简洁起见,省略了thread_create和thread_join,它们基本上是pthread_create和pthread_join或Windows等效程序的包装):

typedef结构{
挥发油修剪;
}线程上下文;
静态无效线程(无效*arg){
ThreadContext*context=(ThreadContext*)arg;
while(上下文->继续修剪){
//做一些快速操作
// ...
//然后在下一次迭代之前睡觉
msleep(100);
}
}
静态int startThread(ThreadContext*context){
context->keepRunning=true;
返回创建的线程(线程、上下文);
}
静态void stopThread(ThreadContext*context){
context->keepRunning=false;
螺纹连接();
}
静态int main(){
语境;
startThread(上下文(&C);
msleep(10000);
停止线程(上下文(&C);
}
编辑:我必须保持Windows兼容性,并交叉编译到一些古老的工具链,因此C11与
stdatomic.h
是不可能的。如果有一种方法可以在Windows上使用常规条件变量,这可能是一种我可以尝试检查我的所有目标是否都支持它们的方法


EDIT2:另外,在这个场景中,我不关心事件的精确顺序,线程应该最终停止(最多经过几次迭代),而不是永远等待连接,但它不必在设置标志后立即停止,也就是说,如果线程再进行几次迭代,它不会造成任何伤害。

在大多数sane体系结构上,在大多数sane编译器访问变量时,
volatile bool
将起作用。然而,本标准并未对此作出保证

POSIX标准保证在异步中断中安全访问
易失性sig_原子\u t
类型。为安全起见,请使用挥发性sig_原子。或者只需使用
pthread\u cond

typedef struct {
    volatile sig_atomic_t keepRunning;
} ThreadContext;
在C11中,有一种方法可以检查访问
bool
是否是原子的且不会被中断,如果
stdatomic.h
中定义了
atomic\u bool\u LOCK\u FREE


一些参考:和。

在大多数sane体系结构上,以及在大多数sane编译器访问变量时,
volatile bool
将起作用。然而,本标准并未对此作出保证

POSIX标准保证在异步中断中安全访问
易失性sig_原子\u t
类型。为安全起见,请使用挥发性sig_原子。或者只需使用
pthread\u cond

typedef struct {
    volatile sig_atomic_t keepRunning;
} ThreadContext;
在C11中,有一种方法可以检查访问
bool
是否是原子的且不会被中断,如果
stdatomic.h
中定义了
atomic\u bool\u LOCK\u FREE


一些参考资料:和。

看看pthread_cancel()和pthread_setcancelstate()。啊,对不起,把代码简化为一个简单的例子,把它搞砸了。
volatile
是上下文的一部分。它应该可以工作,但理论上它是未定义的行为。为什么不将变量
\u原子化
并进行轻松存储?@PSkocik,因为我没有
\u原子化
支持请查看pthread_cancel()和pthread_setcancelstate()。啊,很抱歉,在将代码简化为一个简单的示例时把它弄糟了。
volatile
是上下文的一部分。它应该可以工作,但理论上它是未定义的行为。为什么不将变量
\u原子化
并进行轻松存储?@PSkocik,因为我没有
\u原子化
支持,但“中断时安全”保证与“多线程时安全”相同吗?我可以想象这两种不同的实现,它们并不需要原子化和安全性。我应该能够观察到值最终会变为0(或者,如果这有区别的话,也可以从0变为其他值)。如果您访问的“某物”不是原子的且是“安全的”,那么根据标准,该“某物”的值将变得未指定。@NateEldredge“中断中安全”的意思是,在信号处理程序和其他线程之间。在POSIX上,信号处理程序在任意选择的线程中执行。由此我得出结论,“中断中的安全”也一定意味着“多线程中的安全”。实际上,
sig\u atomic\u t
是在一条指令中访问的。因此,当两个线程在不同的CPU上运行时,一个CPU能够在另一个CPU上观察到指令执行过程中的变量状态时,您必须有一个体系结构。这样的建筑。。这可能不好。我想我在想象一个实现,其中信号处理程序用代码包装,使其所有写入对主程序和其他线程可见,但普通内存写入,即使是对
volatile
变量,也没有这种效果。我并不担心工作线程看到标志的某些“中间”值,而是担心它是否会看到任何更改。但是“中断中的安全”是否保证与“多线程中的安全”相同?我可以想象这两种不同的实现,它们并不需要原子化和安全性。我应该能够观察到值最终会变为0(或者,如果这有区别的话,也可以从0变为其他值)。如果您访问的“某物”不是原子的且是“安全的”,那么根据标准,该“某物”的值将变得未指定。@NateEldredge“中断中安全”的意思是,在信号处理程序和其他线程之间。在POSIX上,信号处理程序在任意选择的线程中执行。由此我得出结论,“中断中安全”m