主线程 子线程死掉_windows主线程等待子线程退出卡死问题

在Windows编程中,使用_Beginthread创建子线程并用WaitForSingleObject等待子线程退出可能导致主线程卡死。这是因为_Beginthread函数的实现不保证线程安全。相比之下,_beginthreadex是线程安全的,它为C/C++线程分配和初始化存储区。子线程结束后,应使用_endthreadex终止线程,以确保内存管理和线程对象的正确清理,避免内存泄露和资源未释放的问题。
摘要由CSDN通过智能技术生成

在windows下调用_beginthread创建子线程并获得子线程id(函数返回值),如果子线程很快退出,在主线程中调用WaitForSingleObject等待该线程id退出,会导致主线程卡死。需要修改_beginthread为_beginthreadex解决该问题。

那么,_beginthread为何会导致WaitForSingleObject卡死,而_beginthreadex却不会呢?这需要查看两个函数的实现。

历史原因

由于C/C++的历史早于线程的出现,因此C/C++的函数并不都是线程安全的。如全局变量errno等。

这就需要一种解决方案。一种方法是利用属于每个线程的数据块,该数据块不会被线程共享,而只能够用于线程自己,这样类似errno的情况便迎刃而解。

此外,C/C++运行库针对特定函数做了改写,使其能够进行线程同步。如malloc函数,由于不能够多线程同时执行内存堆分配操作,因此多线程版本的运行库进行了线程同步处理。

那么,如何让windows系统知道当我们创造新线程时,为我们分配属于线程的存储区呢?利用CreateThread函数并不行(C/C++运行库若获取不到存储器,会自动请求分配对应存储区,因此CreateThread函数实际也可以支持线程安全,但还有其他问题下面再说),因为他只是一个系统API,他不会知道你所写的是C\C++代码。

_beginthreadex函数

_beginthreadex是C/C++运行库创建线程函数,因此可以完美支持C/C++代码的线程安全。其声明如下:

uintptr_t _beginthreadex(void *security,

unsigned stack_size,

unsigned ( __stdcall*start_address )( void *),void *arglist,

unsigned initflag,

unsigned*thrdaddr

);

其参数意义与CreateThread函数完全相同。

重点是要理解该函数为C/C++线程安全做了那些事情。我们可以看到其函数定义。(VS2013路径为C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\threadex.c)

_CRTIMP uintptr_t __cdecl _beginthreadex (void *security,

unsigned stacksize,

unsigned (__stdcall* initialcode) (void *),void *argument,

unsigned createflag,

unsigned*thrdaddr

)

{

_ptiddata ptd;/*pointer to per-thread data*/uintptr_t thdl;/*thread handle*/unsignedlong err = 0L; /*Return from GetLastError()*/unsigned dummyid;/*dummy returned thread ID*/

/*validation section*/_VALIDATE_RETURN(initialcode!= NULL, EINVAL, 0);/** Allocate and initialize a per-thread data structure for the to-

* be-created thread.*/

if ( (ptd = (_p

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值