c ++在线程之间共享状态的最佳方式

c++ Best Way to Share state between threads

场景如下:线程A一直执行,直到它收到线程B的停止信号,线程B不断从控制台读取输入。

实现这个的最佳方法是什么? 例如,我认为我可以将它实现为线程 A 每隔一段时间检查一次的全局变量,线程 B 可以更改为信号 "stop"、

但是我不知道这样是不是正确的方法

您可以像您解释的那样使用变量来发出信号 "stop",但前提是您使用内存栅栏。

有关详细信息,请参阅 Understanding c++11 memory fences

volatile 可能会起作用,但这不是正确的解决方案。你能做的最好的就是检查 std::atomic_bool.

问题可能会作为 "too broad" 结束,但我会尝试回答它(以相同的 "broad" 方式)。

这里唯一可以想到的答案是: "it depends" (c)

一般建议: 尝试并保持简单 (KISS principle)。 从一个简单的解决方案开始(例如您的情况下的互斥体),如果您发现它不令人满意,请将其替换为另一个更复杂但 efficient/scalable/customizable/pleasant 的东西(比如说原子)。如果其中任何一个证明是不够的,进一步增加复杂性(放松原子性,添加无锁的东西,建立基于任务的并发,无论你需要什么)直到找到合适的平衡。

您并不是真的想停止一个线程,而是想在它处于合适的位置时发出停止信号。

它不一定是全局变量。您可以将结构的地址传递给线程。该结构可以包含一个标志。如果另一个线程知道结构的地址,那么它可以更改标志。您可以拥有一个全局结构数组,每个线程对应一个 运行ning。多个线程处理同一数据的方法有很多种。

您可以使用信号。如果您要关闭的线程正在休眠,这些将很方便。

有些人喜欢使用互斥量和条件变量。其他人喜欢使用原子操作。如果您只是测试一个全局 int 以查看它是否非零,则通常不需要互斥量。

在这种情况下,全局 int 可以正常工作。如果你愿意,你可以让它变得不稳定。这告诉编译器不要以阻止您看到它在外部发生更改的方式优化变量。大多数编译器假定全局变量在外部发生变化,并且不需要 volatile 作为全局变量。我可能会因为没有具体说明 volatile 而受到很多批评。

您要确保在线程 运行 之前将全局清零。

确切地说,到纳秒,线程 A 何时会看到更改是另一个问题。如果线程 运行ning 与线程 B 并发,那么它会在更改发生后立即看到它。如果线程 A 处于睡眠状态,它什么也看不到。线程 B 甚至可以在线程 A 启动之前更改标志。当线程实际上被销毁时,发生在线程函数 returns 之后的某个不确定时间 - 只要 OS 绕过它。

您可以使用 std::promisestd::future 而不是在线程之间共享变量,以便清楚地指示信息的流动方式。在最简单的版本中,您可以这样做:

void threadFunc(std::future<void> shallQuit) {
    using namespace std::chrono_literals;
    while (shallQuit.wait_for(0ms) == std::future_status::timeout) {
      // process data.
    }
}

void otherFunc() {
    std::promise<void> signalQuit;
    auto myThread = std::thread(threadFunc, signalQuit.get_future());
    // ... do other stuff.
    signalQuit.set_value();
    myThread.join();
}

作为概括,您可以例如将 promise<> 专门化为不同于 void 的类型,并发送有关您希望线程退出的原因的信息。