C++线程:什么连接完全做?

che*_*gpu 5 c++ multithreading join

以下代码来自Dash的示例std::thread.

#include <iostream>
#include <thread>
#include <chrono>

void foo()
{
    // simulate expensive operation
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

void bar()
{
    // simulate expensive operation
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

int main()
{
    std::cout << "starting first helper...\n";
    std::thread helper1(foo);

    std::cout << "starting second helper...\n";
    std::thread helper2(bar);

    std::cout << "waiting for helpers to finish..." << std::endl;
    helper1.join();
    // std::cout << "after join... \n";
    helper2.join();

    std::cout << "done!\n";
}
Run Code Online (Sandbox Code Playgroud)

join阻塞当前线程,直到*this标识的线程完成其执行.

调用后线程是否执行join

如果我std::cout << "after join... \n"在第一次连接之后添加after join...,done!则将按顺序输出,而不会延迟,这就像在第二次之后放置一样join.

具体来说,整个效果是:顺序打印前三行,然后休眠一段时间,最后顺序打印最后两行,没有延迟.

a.join();
b.join();
cout << "something...";
// or
a.join();
cout << "something...";
b.join();
Run Code Online (Sandbox Code Playgroud)

令我困惑的是:为什么这两种方式有相同的效果?究竟join做了什么?

Joz*_*ény 6

两个线程同时启动并执行相同的长度.因此,join在您的情况下没有做太多 - 两个线程同时开始并在同一时间结束.

  1. 线程1启动,开始睡眠1秒钟
  2. 线程2启动,开始睡眠1秒钟
  3. 加入1被叫 - 程序将等待1秒后传递给线程1完成
  4. 这意味着线程2也完成了
  5. 加入2被叫,这简直是直通,因为线程2已经完成

如您所见,在步骤5之前或之后打印任何内容都不会改变.

一个更好的例子是:

#include <iostream>
#include <thread>
#include <chrono>

using namespace std;

void foo()
{
    // simulate expensive operation
    cout << "Foo Start" << endl;
    this_thread::sleep_for(chrono::seconds(1));
    cout << "Foo Stop" << endl;
}

void bar()
{
    // simulate expensive operation
    cout << "Bar Start" << endl;
    this_thread::sleep_for(chrono::seconds(2));
    cout << "Bar Stop" << endl;
}

int main()
{
    thread helper1(foo);
    thread helper2(bar);

    helper1.join();
    cout << "Joined Foo... \n";
    helper2.join();
    cout << "Joined Bar... \n";
}
Run Code Online (Sandbox Code Playgroud)

您将观察到如果线程foo持续1秒并且线程条持续2秒,那么"Joined Foo"和"Joined Bar"输出将在它们之间延迟1秒.如果你把foo的持续时间反转为2秒,bar反转1秒,那么2秒后会打印"Joined Foo"输出,之后会立即打印"Joined Bar".