从主线程触发一个线程中的动作的防弹方法?
Posted
技术标签:
【中文标题】从主线程触发一个线程中的动作的防弹方法?【英文标题】:Bulletproof way to trigger an action in one thread from the main thread? 【发布时间】:2021-12-15 09:38:14 【问题描述】:我有一个线程在程序启动时启动并连续运行(我使用的是 pthreads)。我需要从主线程向线程发送命令。我可以设置一个全局变量,但这似乎有风险,因为如果辅助线程和主线程尝试同时访问它怎么办?我可以将变量包装在互斥锁中,但这有必要吗?如果我只是在主线程中放置一个执行如下代码的按钮会怎样:
// main thread
if(!trigger_variable)
trigger_variable=1;
然后,在第二个线程中我使用这个:
// other thread
if(trigger_variable)
do_something();
trigger_variable=0;
这是否足够强大以避免使用互斥锁?
【问题讨论】:
没有足够的信息。每个线程是如何触发检查条件的?是否涉及其他线程?这些是唯一读/写变量的地方吗? 您希望工作线程在等待来自主线程的命令时休眠吗?如果是这样,您可能想了解producer/consumer problem 并查看pthread condition variables。 @kaylum 没有涉及任何其他线程。只是主线程触发了第二个线程。除了这两个示例之外,不会有任何其他读/写操作。 @Andreas 第二个线程实际上一直在做一些事情,所以这不是一个生产者/消费者的情况(尽管我的应用程序的其他部分都是这样)。我只需要告诉线程在用户触发时修改其行为。 【参考方案1】:trigger_variable
只要是atomic type 就可以工作;对于常规/非原子类型,它将调用未定义的行为,因为您将有两个线程在没有任何同步的情况下读取和写入相同的内存。
但是,设置共享变量并不完全是“发送命令”,而是设置一个共享状态,因此我不会为此目的称其为“防弹”。例如,如果您想快速连续发送两个命令,则很难保证两个命令都被接收,因为对变量的第二次更改可能会在子线程有机会看到第一个值之前覆盖第一个.
如果您希望能够正确发送命令(例如,让子线程按照发送命令的顺序接收每个命令),一种相对简单的方法是让主线程创建一个 @ 987654322@ 并将管道的数据读取文件描述符提供给子线程。然后主线程可以write()数据写入文件描述符上的一个字节,只要它想让子线程做某事,子线程可以read()那个字节并做出适当的反应。
【讨论】:
使用管道是个好主意!似乎这样会更安全,也更便携,因为它不需要仅在后来的 C 标准中可用的原子数据类型。【参考方案2】:根据§5.1.2.4 ¶25 and ¶4 of the official ISO C11 standard,两个不同的线程以无序方式使用非原子操作读取和写入同一内存位置会导致undefined behavior。
但是,如果您改用atomic types 或atomic operations libary,那么您的计划应该会奏效。
【讨论】:
以上是关于从主线程触发一个线程中的动作的防弹方法?的主要内容,如果未能解决你的问题,请参考以下文章
MFC:如何从主线程使用 MsgWaitForMultipleObjects() 来等待多个线程完成使用 SendMessage()?