C++线程:join到底是做什么的?

5
以下代码来自于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";
}

join函数会阻塞当前线程直到标识为*this的线程执行结束。

join调用后,线程是否会执行?

如果我在第一个join后面添加std::cout << "after join... \n",则after join...done!将按顺序连续输出,没有延迟,就像它们被放置在第二个join之后一样。

具体来说,整个效果是:先连续打印前三行,然后睡眠一段时间,最后再连续打印后两行而没有延迟。

a.join();
b.join();
cout << "something...";
// or
a.join();
cout << "something...";
b.join();

令我困惑的是:为什么这两种方式有相同的效果?join到底是做了什么呢?该函数与将一个数组转换为字符串。只需传入一个参数,即可指定用于连接每个数组元素的字符。

1
http://www.cplusplus.com/reference/thread/thread/join/ - Martin Verjans
4个回答

8

你的两个线程同时启动并且运行时间相同。因此,在你的情况下,join 没有太多作用 - 两个线程同时启动并同时结束。

  1. 线程1开始,开始休眠1秒
  2. 线程2开始,开始休眠1秒
  3. 调用1的join - 程序将等待1秒钟以使线程1完成
  4. 这意味着线程2也已经完成了
  5. 调用2的join,由于线程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";
}

你会发现,如果线程foo持续1秒,而线程bar持续2秒,则“Joined Foo”和“Joined Bar”输出将在它们之间有1秒的延迟。如果你将这两个时间反过来,即foo持续2秒,bar持续1秒,则“Joined Foo”输出将在2秒后打印,“Joined Bar”紧接着立即打印。

2
在一句话中,连接器等待被连接方完成其执行。

1

Join方法会阻塞当前线程,即当前线程不会继续执行,直到调用join方法的线程执行完毕。次要线程在构造函数调用时开始运行。 例如,主线程将停止执行,直到线程a完成其运行,然后主线程将恢复执行。


0
我将举个例子来说明join的作用和用途。假设我有一大批计算任务B需要完成,我想要使用多线程并行处理,以利用我拥有的多个CPU核心。
我们称启动所有这些的线程为main。假设我有四个核心,因此我将使用四个线程。从线程main中,我创建了四个新的“工作”线程,并将它们都分配了B的一个子集来处理。
现在我有5个正在运行的线程。但是在我的main线程中,我想要使用计算结果,所以我必须等待其他线程完成。这可以通过调用join来实现,通过依次在四个线程上调用join,我确保它们都完成计算,以便我可以安全地读取和使用结果。
通过在四个工作线程之一上从main调用join,我使main等待该工作线程。因此,在等待时,main将停止,这是一种“阻塞调用”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接