gpt4 book ai didi

c++ - 调用 std::thread.detach 时的意外行为

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:03:00 25 4
gpt4 key购买 nike

我一直在努力加深对 C++ 线程的理解,为此我编写了以下示例:

#include <functional>
#include <iostream>
#include <thread>

class Test {
public:
Test() { x = 5; }

void act() {
std::cout << "1" << std::endl;
std::thread worker(&Test::changex, this);
worker.detach();
std::cout << "2" << std::endl;
}

private:
void changex() {
std::cout << "3" << std::endl;
x = 10;
std::cout << "4" << std::endl;
}

int x;
};

int main() {
Test t;
t.act();

return 0;
}

对我来说,当使用 -pthread 链接的 g++ 编译时,我应该得到以下输出:

1
2
3
4

因为 cout 调用的顺序是这样的。但是,输出不一致。 1 和 2 总是按顺序打印,但有时 3 和或 4 会被省略或重复打印。 12123123412344

我的工作原理是主线程在工作线程开始工作或完成之前退出,从而导致输出遗漏。我可以立即想到解决这个问题的方法,创建一个全局 bool 变量来表示工作线程何时完成,主线程在退出前等待状态更改。这缓解了这个问题。

但是,对我来说,这感觉像是一种非常困惑的方法,可能有一个更干净的解决方案,尤其是对于线程中可能经常出现的此类问题。

最佳答案

只是一些一般性建议,适用于在 C++ 中使用原始 pthread 和包装在 std::thread 中的 pthread:获得可读、可理解和可调试行为的最佳方法是使线程同步和生命周期管理明确。 IE。避免使用 pthread_kill、pthread_cancel,并且在大多数情况下,避免分离线程,而是进行显式连接。

我喜欢的一种设计模式是使用标准原子标记。当主线程想要退出时,它将原子标志设置为 true。工作线程通常在一个循环中完成它们的工作,并经常检查原子标志,例如每圈循环一次。当他们发现 main 命令他们退出时,他们清理并返回。主线程然后加入:s 与所有 worker 。

有一些特殊情况需要格外小心,例如,当一名工作人员卡在阻塞的系统调用和/或 C 库函数中时。通常,该平台提供了摆脱此类阻塞调用的方法,而无需求助于例如pthread_cancel,因为线程取消在 C++ 中的效果非常差。如何避免阻塞的一个示例是 getaddrinfo_a 的 Linux 联机帮助页,即异步网络地址转换。

另一个不错的设计模式是当员工 sleep 时,例如选择()。然后,您可以在 main 和 worker 之间添加一个额外的控制管道。 Main 通过 send() 向 worker 发出退出信号:在管道上发送一个字节,从而在 select() 中休眠时唤醒 worker。

关于c++ - 调用 std::thread.detach 时的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54952410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com