寻找std :: join行为的澄清

时间:2018-02-14 04:14:21

标签: c++ multithreading mutex

我一直在学习更多关于多线程和锁定的知识,这让我了解了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. 打印出星星后执行完成,然后我的print语句执行

  3. th2执行开始和结束

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

    无论如何,我的解释没有任何意义,因为它似乎与单线程进程相同。救命啊!

    TLDR;

    致电加入时会发生什么?新线程开始,但主线程会发生什么?如果主线程阻塞了,为什么不是我的例子呢?

    由于

    编辑:

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

1 个答案:

答案 0 :(得分:2)

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

  

致电加入时会发生什么?新线程开始了,但是   主线程会发生什么?如果主线程阻塞,为什么   我的例子不是这样的吗?

th1.join()将阻止执行当前线程(在这种情况下是运行函数main()的执行线程),直到执行的线程由{ {1}}完成并返回。

现在,这与th1th2之前是否完成无关 - (无法保证线程th1进入函数并在线程{{{{}之前选择锁定1}})。所有这些方法都说,&#34; th1完成之前不会继续&#34;。

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

th2
th1完成之前,

永远不会被执行。

错误的例子:

  • 关于异常安全。首选std::cout << "In between thread joins" << std::endl; 。此外,请选择 cppreference.com
  • th1中的std::lock_guard未受到保护,是的,std::cout ...没有竞争对手,但在多个线程使用时无法交错字符输出
  • 如果您需要某些功能之间的相对排序,int main()可能不是您想要使用的。而且,更喜欢更高的抽象,例如std::cout
  • 代码方式,即使您std::thread中的std::async被假定为不可分割的交易,也要将std::cout ...放在它之前,int main()之后只是一个欺骗性的交易。我会在代码上互相关注。