【问题标题】:How can a thread run a loop until joined?线程如何在加入之前运行循环?
【发布时间】:2015-11-04 12:19:05
【问题描述】:

使用std::thread 运行一个无限循环的方法,有没有办法让循环查询线程是否已被请求加入...或者我是否必须手动添加一个“exitThread”标志?

换句话说,isJoined 会是什么样子(未经测试的伪代码):

std::atomic<int> global_counter (0);

void Run()
{
  while(!isJoined())
  {
    doSomething();
    ++global_counter;
  }
}

int main()
{
  thread t(Run);
  Sleep(10000);
  t.join();
  cout << "Iterated " << global_counter << "times" << endl;
}

【问题讨论】:

    标签: c++ multithreading c++11 stl


    【解决方案1】:

    您要做的不仅是加入线程,还要向它发送消息。这两件事是不同的,你需要两者都做。

    要向线程发送消息,您使用条件变量向其发送信号。既然你知道了你需要的东西的名字,你可以google一下,你会发现很多很好的教程解释了如何使用这个概念给线程发信号,所以我觉得这里没有必要详细介绍。

    【讨论】:

    • 啊,我有点误解了 join 的作用...而不是终止线程,它只是阻塞当前/调用线程直到另一个线程终止。它没有尝试通知它应该退出的线程,它只是等待它这样做?这清楚地表明需要明确的信号(标志或条件变量)。
    • @Mr.Boy join 是一个简单的waitpid 调用,它不会通知目标线程任何事情,只是等待。检查手册页。
    • 人们总是过度设计事物,因为不会发生任何不好的事情,只是效率低下。但如果你知道细节,更简单、更高效的设计也适合
    【解决方案2】:

    使用变量表示退出:

    volatile boolean request_exit = false;
    

    在循环中测试变量:

    while(!request_exit) { do work }
    

    然后在join前设置变量:

    request_exit = true;
    t.join();
    

    【讨论】:

    • 请注意,仅使用volatile,您并没有从程序中删除任何随机性,只是确保该值最终会被另一个线程读取,而如果没有关键字,它可能永远不会被读取.它不保证任何操作顺序。
    • 一个设计良好的多线程程序并不保证退出的顺序,它只保证目标线程能看到它。正确退出是目标线程的职责。
    • 所以它应该使用原子布尔值?
    • @Mr.Boy 默认是原子的
    • 没有什么能阻止 cpu 从缓存中读取,甚至是锁/屏障。他们只保证我解释的顺序和原子。例如,core1: atomic{x=1,y=1}, atomic{x=2,y=2} 屏障 send_signal。现在 core2 可能会读取 {x=1,y=1} 或 {x=2,y=2} 但在 core2 收到信号后,core2 只能看到 {x=2,y=2}。屏障仅确保分配发生在信号之前,它确实确保 core2 将看到新值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多