【问题标题】:C++ communication between threads线程之间的 C++ 通信
【发布时间】:2013-12-15 14:45:33
【问题描述】:

我有几个类,每个类在不同的线程中打开一个不同的程序,并使用 CreateProcess 执行/保存有关它的信息(如果有更面向 C++ 的方式来做到这一点,请告诉我——我看过了)。

某些类依赖于正在运行的其他程序之一。即如果A 停止,B 必须停止。不久前我编写了这段代码,然后我的解决方案是拥有一个具有静态函数的类,该函数运行各种程序和保持其“状态”的静态成员变量。我也在使用CreateThread

回想起来,这种方法看起来……脆弱而笨拙。 我不知道使用这样的“静态类”是否是一种好习惯(特别是回想一下初始化状态成员变量是多么尴尬)。我想让每个类都包含自己的运行功能。但是,我正在考虑的问题是如何让 B 班知道 A 是否尴尬地停止了。他们仍然需要知道一种方法来了解彼此的状态。请注意,我想在这次返工中使用std::thread,而且我对多线程几乎没有经验。感谢您的帮助。

【问题讨论】:

    标签: c++ multithreading c++11 thread-safety


    【解决方案1】:

    好吧,在多进程应用程序中,您将使用管道/文件将信息从一个进程传输到另一个进程(甚至可能是子进程的返回值)。所以也可以尝试共享内存,尽管它可能会有些挑战(如果您愿意,请查看 Boost.Interprocess)。

    在多线程应用程序中,您基本上可以使用相同的选项:

    • 您可以使用共享内存(前提是您同步访问)
    • 您可以使用队列将信息从一个线程传递到另一个线程(例如使用管道)

    所以这两者真的很相似。

    遵循 Tony Hoare 的规则,您通常应该通过通信进行共享,而不是通过共享进行通信,这意味着将队列/管道特权分配给共享内存;然而,对于一个布尔标志,共享内存可以证明更容易放置:

    void do_a(std::atomic_bool& done) {
         // do things
         done = true;
    }
    
    int main() {
        std::atomic_bool done = false;
    
        auto a = std::async(do_a, done);
    
        auto b = std::async([](std::atomic_bool& done) {
            while (not done) {
                std::cout << "still not done" << std::endl;
                sleep(1);
            }
        });
    
        // other stuff in parallel.
    }
    

    当然,您甚至可以将此标志放在std::shared_ptr 中以避免悬空引用的风险。

    【讨论】:

    • 遗憾的是,这甚至无法编译。我使用 VS11 并感觉有一些关于原子的未实现的东西。
    • @user193138:好吧,如果你没有访问原子的权限,你可以回到互斥锁。实际上,如果您想等待(不采取任何行动)直到某事完成,互斥体+条件变量的设计会减少资源消耗。
    • 我应该只将一个互斥锁传递给每个类吗?我不确定作为一种让每个班级都具有全球访问权限的方法是否有意义。再说一次,我在这方面一无所知,抱歉)
    • 如果您能按照您的建议提供队列示例,那就太好了...
    • @user18490:不幸的是,与其他语言不同,C++ 中没有标准的多线程队列(AFAIK 没有出现在 C++17 中)。如果 Boost 是一个选项,我建议查看 this page,它显示了无锁和无等待堆栈/队列的情况。