分享

CloseHandle(),TerminateThread(),ExitThread()的区别

 戴维图书馆 2017-07-20

线程的handle用处:

线程的handle是指向“线程的内核对象”的,而不是指向线程本身.每个内核对象只是内核分配的一个内存块,并且只能由内核访问。该内存块是一种数据结构,它的成员负责维护对象的各种信息(eg: 安全性描述,引用计数等)。

 

CloseHandle()

在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

但是这个handle并不能完全代表这个线程,它仅仅是线程的一个“标识”,系统和用户可以利用它对相应的线程进行必要的操纵。如果在线程成功创建后,不再需要用到这个句柄,就可以在创建成功后,线程退出前直接CloseHandle掉,但这并不会影响到线程的运行。

 

不执行CloseHandle() 带来的后果:

若在线程执行完之后,没有通过CloseHandle()将引用计数减1,在进程执行期间,将会造成内核对象的泄露,相当与句柄泄露,但不同于内存泄露, 这势必会对系统的效率带来一定程度上的负面影响。但是,请记住,当进程结束退出后,系统仍然会自动帮你清理这些资源。但是在这里不推荐这种做法,毕竟不是 一个良好的编程习惯!
( 应用程序运行时,有可能泄露内核对象,但是当进程终止运行时,系统能确保所有内容均被正确地清除。另外,这个情况是用于所有对象,资源和内存块,也就是说,当进程终止时,系统将保证不会留下任何对象。)

 

TerminateThread()

函数的声明如下:

BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode); 作用: 在线程外终止一个线程,用于强制终止线程。 参数说明: HANDLE htread:被终止的线程的句柄,为CWinThread指针。 DWORD dwExitCode:退出码。 返回值: 函数执行成功则返回非零值,执行失败返回0。调用getlasterror获得返回的值。

 

 

听过无数次不要TerminateThread,只是工作中常用,貌似也没有什么问题。今天在高强度测试中发现了一个不可原谅的错误。参看下面的例子

 

  1. DWORD __stdcall mythread(void* )  
  2. {  
  3.     whiletrue )  
  4.     {  
  5.         char* p = new char[1024];  
  6.   
  7.         delete p;  
  8.     }  
  9. }  
  10.   
  11.   
  12. int _tmain(int argc, _TCHAR* argv[])  
  13. {  
  14.   
  15.     HANDLE h = CreateThread(NULL, 0, mythread, NULL, 0, NULL);  
  16.   
  17.     Sleep(1000);  
  18.   
  19.     TerminateThread(hThread , 0);  
  20.     hThread = NULL;  
  21.   
  22.     char* p = new char[1024]; //这里会死锁,过不去   
  23.   
  24.     delete p;  
  25.   
  26.     return 0;  
  27. }  
DWORD __stdcall mythread(void* )
{
while( true )
{
char* p = new char[1024];

delete p;
}
}


int _tmain(int argc, _TCHAR* argv[])
{

HANDLE h = CreateThread(NULL, 0, mythread, NULL, 0, NULL);

Sleep(1000);

TerminateThread(hThread , 0);
hThread = NULL;

char* p = new char[1024]; //这里会死锁,过不去

delete p;

return 0;
}

 

为什么死锁呢?new操作符用的是小块堆,整个进程在分配和回收内存时,都要用同一把锁。如果一个线程在占用该锁时被杀死(即临死前该线程在new或delete操作中),其他线程就无法再使用new或delete了,表现为hang住。

<核心编程>里明确提醒不要TerminateThread,但原因并不是血淋淋滴。今天发现的这个bug印证了此书的价值。

另注:许多临时的网络操作经常用TerminateThread,作为网络不通时的退出机制,以后要改改了。比如让该线程自生自灭,自行退出。

ExitThread是推荐使用的结束一个线程的方法,当调用该函数时,当前线程的栈被释放,然后线程终止,相对于TerminateThread函数来说,这样做能够更好地完成附加在该线程上的DLL的清除工作

转自:http://blog.csdn.net/anye3000/article/details/7470674

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多