C++ thread.join 与 terminate

C++11 std::thread join

    • 主要函数
    • 注意事项
    • 原因
    • 解决方案

std::thread 是C++11的新特性,对于windows来说,取代了原来的静态方法的创建方式

DWORD WINAPI ThreadUtil::ThreadProc(LPVOID lpParameter)

主要函数

joinable():用于检测线程是否有效。

joinable : 代表该线程是可执行线程。

not-joinable :通常一下几种情况会导致线程成为not-joinable

 1) 由thread的缺省构造函数构造而成(thread()没有参数)。

 2) 该thread被move过(包括move构造和move赋值)

 3) 该线程调用过join或者detach

thread::join(): 阻塞当前线程,直至 *this 所标识的线程完成其执行。*this 所标识的线程的完成同步于从 join() 的成功返回。
该方法简单暴力,主线程等待子进程期间什么都不能做。thread::join()会清理子线程相关的内存空间

注意事项

在析构之前一定要显式调用,否则程序会出现crash

if(thread.joinable())
    thread.join()

测试代码

  1. ThreadUtil.h文件
class ThreadUtil
{
public:
   static DWORD WINAPI ThreadProc(LPVOID lpParameter);
   int threadTest();
   void testJoin();
   //~ThreadUtil();

public:
    std::thread testThread;
};

2.ThreadUtil.cpp文件

其中threadTest 与 ThreadProc 是传统的创建与调用thread的方式

#include "pch.h"
#include "ThreadUtil.h"
#include 
#include 
#include 
using namespace std;

DWORD WINAPI ThreadUtil::ThreadProc(LPVOID lpParameter)
{
    for (int i = 0; i < 5; ++i)
    {
        std::cout << "子线程:i = " << i << std::endl;
        Sleep(100);
    }
    return 0L;
}

int ThreadUtil::threadTest()
{
    //创建一个线程
    HANDLE thread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    //关闭线程
    CloseHandle(thread);

    //主线程的执行路径
    for (int i = 0; i < 5; ++i)
    {
        std::cout << "主线程:i = " << i << std::endl;
        Sleep(100);
    }

    return 0;
}

void ThreadUtil::testJoin()
{
    if (testThread.joinable())
    {
        std::cout << "is joinable" << std::endl;
        testThread.join();
    }
    testThread = std::thread([]() {
        std::cout << "is ini" << std::endl;
    });
}

 //ThreadUtil::~ThreadUtil() 
 //{
 //    if (testThread.joinable())
 //    {
 //        testThread.join();
 //    }
 //}

main函数


int main()
{
    ThreadUtil threadUtil;
    threadUtil.testJoin();
    std::cout << "Hello World!\n"; 
}

先把析构中的代码去除,调用testJoin,直接crash在thread的析构函数中,会主动的调用terminate函数

C++ thread.join 与 terminate_第1张图片
C++ thread.join 与 terminate_第2张图片
注释掉析构函数中的代码,一切ok

原因

C++标准中希望程序员必须主动的去调用join
所以在thread的析构函数中,会判断线程是否为joinable,如果joinable,就会调用terminate,这就是上面程序出现crash的原因

那么为什么C++标准中不去显式的调用join函数或者detached函数,让程序处于不可联结的状态
1.若调用join,线程会一直等待子线程的退出,耗时很长
2.若调用detached,切断了子线程与主线程之间的链接,其中的lambda表达式可能使用了全局或者局部的变量,指针可能出现悬空的状态

解决方案

封装std::thread代码,具体例子再研究一下

参考链接

C++11: What happens if you don’t call join() for std::thread
std::thread对象的析构

你可能感兴趣的:(C++编程)