寻找 std::join 行为的澄清

Looking for clarification of std::join behavior

本文关键字:std join 寻找      更新时间:2023-10-16

我一直在学习更多关于多线程和锁定的知识,这让我想到了 http://www.cplusplus.com/reference/thread/thread/join/提供的基本示例

该页面提供的基本解释是:

该函数在线程执行完成后返回。

好的,听起来有点像我们启动了一个线程,当我们启动的线程完成时,我们将恢复调用线程。

下面是来自站点的一些示例代码,我已向其添加了一个 print 语句。

#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>
std::mutex mtx;
void print_block (int n, char c) {
mtx.lock();
for (int i = 0; i < n; i++)
{
std::cout << c;
}
std::cout << std::endl ;
mtx.unlock();
return;
}
int main()
{
std::thread th1(print_block, 50, '*');
std::thread th2(print_block, 60, '$');
th1.join();
//my print statement
std::cout << "In between thread joins" << std::endl;
th2.join();

return 0;
}

根据我看到的联接描述,我希望输出为:

**

**

在螺纹连接之间

$$$$

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

我的逻辑是:

主线程
  1. 调用 th1.join,因此主线程停止执行,直到 th1.join 完成。

  2. th1 执行在打印出星星后完成,然后我的 print 语句执行

  3. TH2 执行开始和结束

实际上情况并非如此,th2 可以在 th1 之前执行,我的 print 语句通常排在最后。 连接实际上对主线程有什么作用? 它似乎并没有像我一直在线阅读那样真正阻止它。

无论如何,我的解释毫无意义,因为它似乎与单线程进程相同。 帮助!

TLDR;

当你调用加入时,到底会发生什么? 新线程开始,但主线程会发生什么? 如果主线程确实阻塞,为什么我的例子不是这种情况?

谢谢

编辑:

我想我明白了。 出于某种原因,我认为 th1 在调用 join 时开始执行。 th1 在调用构造函数时开始执行。 Join 将阻塞主线程,直到 th1 在开始执行后完成。 谢谢大家!

这个例子很糟糕(原因如下);

当你调用加入时,到底会发生什么?新线程开始,但是 主线程会发生什么变化?如果主线程确实阻塞,为什么 我的例子不是这样吗?

th1.join()将阻止当前线程(在本例中为运行函数main()的执行线程)的执行,直到th1表示的执行线程完成并返回。

现在,这与th2是否在th1之前完成无关 - (不能保证线程th1进入函数并在线程th2之前选择锁)。这种方法只是说,"在th1完成之前不要继续"。

所以,是的,th2可能会在th1之前完成,但是

std::cout << "In between thread joins" << std::endl;

th1完成之前永远不会被执行。


不好的例子:

  • 关于异常安全。更喜欢std::lock_guard.从今以后,请首选使用cppreference.com
  • int main()中的std::cout ...不受保护,是的,std::cout没有种族,但在被多个线程使用时不能交错字符输出
  • 如果您需要某些函数之间的相对排序,则可能不是您想要使用的std::thread。而且,更喜欢更高的抽象,例如std::async.
  • 从代码上讲,即使int main()中的std::cout ...被认为是不可分割的交易,将th1.join()放在它之前,th2.join()之后也只是一种欺骗。我会让连接在代码上相互跟随。