C++多线程之join()函数
C++多线程使用中经常会涉及到的一个函数join()
,该函数调用主要是用来进行线程的流程控制,或者说阻塞。关于join()
函数,我们只需要理解两个主要的关键点:
- 哪个线程对象调用这个
join()
函数? - 在哪个线程环境下调用这个
join()
函数?
我们先来看一下示例:
#include <iostream>
#include <thread>
void endless_wait()
{
std::cout << "endless_wait() start." << std::endl;
while (true)
{
;
}
std::cout << "endless_wait() end." << std::endl;
}
int main(void)
{
std::cout << "The main thread start." << std::endl;
std::thread usedWait(endless_wait);
usedWait.join();
std::cout << "The main thread end." << std::endl;
return 0;
}
输出结果如下:
The main thread start.
endless_wait() start.
下面我们简单分析一下:启动程序,main()
函数执行,开辟一个新线程对象usedWait
调用函数endless_wait()
。程序进行死循环,因此会一直等待下去,没有输出后面的两行endless_wait() end
与The main thread end
。
现在我们回答一下调用join()
函数后,上述的两个关键点问题:
- 上述程序,可以轻易看出开辟一个线程对象
usedWait
调用join()
函数. - 线程
usedWait
是在主线程环境下进行调用join()
函数,因此主线程必须等待子线程usedWait
执行结束,才可以继续往下执行.
C++多线程之detach()函数
线程中的detach()
函数为将对象表示的线程与调用线程进行分离,允许进行独立执行。两个线程都可以继续允许,不会存在任何方式的阻塞或同步。但是,如果任何一个结束执行后,其资源将会释放。
我们分析一下下面的代码:主函数main()
里面开辟3个子线程,同时这3个子线程都进行detach()
函数脱离主线程环境。因此,我们发现输出结果,顺序比较混乱。这就是因为3个子线程脱离主线程的环境独立运行,主线程不会管子线程是否运行结束,同样3个子线程也是独立运行。这样带来的问题主要是:如果主线程中存在资源被子线程调用,这时候子线程与主线程脱离关系,独立运行。如果主线程提前结束,那么子线程将会无法调用该资源,导致不正确的结果。
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::sleep_for
#include <chrono> // std::chrono::seconds
void pause_thread(int n)
{
std::this_thread::sleep_for(std::chrono::seconds(n));
std::cout << "pause of " << n << " seconds ended\n";
}
int main()
{
std::cout << "Spawning and detaching 3 threads...\n";
std::thread(pause_thread, 1).detach();
std::thread(pause_thread, 2).detach();
std::thread(pause_thread, 3).detach();
std::cout << "Done spawning threads.\n";
std::cout << "(the main thread will now pause for 5 seconds)\n";
// give the detached threads time to finish (but not guaranteed!):
pause_thread(5);
return 0;
}
输出结果:
Spawning and detaching 3 threads...
Done spawning threads.
(the main thread will now pause for 5 seconds)
pause of 1 seconds ended
pause of 2 seconds ended
pause of 3 seconds ended
pause of 5 seconds ended
小结
线程模块的join()
函数两个关键点:1.哪个线程对象调用join()
函数?调用该函数对象,必须等待这个线程的所有事情结束,join()
函数才返回。2.在哪个线程环境下调用join()
函数?如果一个线程对象在一个线程环境中调用这个join()
函数,那么这个线程环境就会被阻塞,知道这个线程对象执行完毕后才继续往下执行。
线程模块的detach()
函数使用时候一定要注意资源的利用,因为如果线程对象一旦detach
之后,那么其将独立运行,与之前的线程环境没有关系。很可能会导致内存资源已经不存在,还在继续调用,这样会导致不正确的结果。
参考文献
http://www.cplusplus.com/reference/thread/thread/join/
http://www.cplusplus.com/reference/thread/thread/detach/