关于多线程的一些龌龊事

作者在 2011-12-15 23:02:07 发布以下内容
2009.11.27 写的

  与信号量、互斥等内核对象比起来线程内核比较龌龊,它在创建时具有2次计数。在《windows核心编程》中说过,如果不需要线程的句柄则可以关闭该句柄(这时递减一次计数),线程在自然结束时还会自动递减一次计数,这样线程内核对象就被系统回收了。今天,我在写多线程时,发现了许多应该注意的问题。

 

一、我在这关闭线程句柄为什么不行?

for (int i = 0; i < 10; ++i)

{

  HANDLE thread = (HANDLE)::_beginthreadex(Null, 0, &WorkerThread, param, 0, 0);

  ::CloseHandle(thread); // !!!!!!!!!!!!!!!!!!!!

}

哈哈,看出什么问题了吗?按照上面说的线程内核对象具有2次计数,在这里关闭该句柄照逻辑应该没什么事,但事实上是不行的。这里关闭的句柄是【进程相关的】引用计数,因此再次调用_beginthreadex返回的句柄有可能还是上次分配的句柄。意外吧,吃惊吧。知道怎么做了吧?对就是把关闭句柄放在另外一个循环中。

 

二、不是线程内核对象没有回收吗,怎么不能用了?

如果m_threads是一个已被关闭的线程句柄数组,那么下面的调用会失败。

::WaitForMultipleObjects(m_init, m_threads, TRUE, INFINITE);

线程句柄如果被关闭,那么和【进程相关的】引用计数被递减,如果递减到【进程相关的引用计数为0】,这时m_threads都是无效句柄(可能系统已经把进程的句柄表给清除了)。但是线程内核对象还是存活的,它还有一次引用计数。可怕吧?颤抖了吧?只有线程自然终止或者强制终止TerminateThread,线程内核对象才会被系统回收。

Windows | 阅读 1109 次
文章评论,共0条
游客请输入验证码
浏览14401次