CreateThread与_beginthread的区别

原文地址 http://820808.blog.51cto.com/328558/76160

 

在写 c++ 代码时,一直牢记着一句话:决不应该调用 CreateThread 。相反,应该使用 Visual   C++ 运行期库函数 _beginthreadex
好像 CreateThread 函数就是老虎,既然这样为什么微软要开发这个函数呢?
从网上找到的相关资料,现在汇总一下,在此对相关人员进行感谢!
 
摘自《 windows   核心编程》:  
     CreateThread
函数是用来创建线程的 Windows 函数。不过,如果你正在编写 C/C++ 代码,决不应该调用 CreateThread 。相反,应该使用 Visual   C++ 运行期库函数 _beginthreadex 。如果不使用 Microsoft Visual   C++ 编译器,你的编译器供应商有它自己的 CreateThred 替代函数。  
     
若要使多线程 C C++ 程序能够正确地运行,必须创建一个数据结构,并将它与使用 C/C++ 运行期库函数的每个线程关联起来。当你调用 C/C++ 运行期库时,这些函数必须知道查看调用线程的数据块,这样就不会对别的线程产生不良影响。  
   1.
每个线程均获得由 C/C++ 运行期库的堆栈分配的自己的 tiddata 内存结构。  
   2.
传递给 _beginthreadex 的线程函数的地址保存在 tiddata 内存块中。传递给该函数的参数也保存在该数据块中。  
   3._beginthreadex
确实从内部调用 CreateThread ,因为这是操作系统了解如何创建新线程的唯一方法。  
   4.
当调用 CreatetThread 时,它被告知通过调用 _threadstartex 而不是 pfnStartAddr 来启动执行新线程。       还有,传递给线程函数的参数是 tiddata 结构而不是 pvParam 的地址。   
5. 如果一切顺利,就会像 CreateThread 那样返回线程句柄。如果任何操作失败了,便返回  NULL  

     _beginthreadex
_beginthread 函数的区别。 _beginthread 函数的参数比较少,因此比特性全面的 _beginthreadex 函数受到更大的限制。  
 
例如,如果使用 _beginthread ,就无法创建带有安全属性的新线程,无法创建暂停的线程,也   无法获得线程的 ID 值。
 
下面摘录 Csdn 中的 Holly ()的帖子进行解释,再次表示感谢。
Holly ():
oldworm 提供了很好的使用的例子,而且也运用了编译控制!  
 
我来解释一下理论上的区别:  
 CreateThread
_beginthread _beginthreadex 都是用来启动线程的,但大家看到 oldworm 没有提供 _beginthread 的方式,原因简单, _beginthread _beginthreadex 的功能子集,虽然 _beginthread 内部是调用 _beginthreadex 但他屏蔽了象安全特性这样的功能,所以 _beginthread CreateThread 不是同等级别, _beginthreadex CreateThread 在功能上完全可替代,我们就来比较一下 _beginthreadex CreateThread!  
   
  CRT
的函数库在线程出现之前就已经存在,所以原有的 CRT 不能真正支持线程,这导致我们在编程的时候有了 CRT 库的选择,在 MSDN 中查阅 CRT 的函数时都有:  
  Libraries  
  LIBC.LIB   Single   thread   static   library,   retail   version    
  LIBCMT.LIB   Multithread   static   library,   retail   version    
  MSVCRT.LIB   Import   library   for   MSVCRT.DLL,   retail   version    
 
这样的提示!  
 
对于线程的支持是后来的事!  
 
这也导致了许多 CRT 的函数在多线程的情况下必须有特殊的支持,不能简单的使用 CreateThread OK  
 
大多的 CRT 函数都可以在 CreateThread 线程中使用,看资料说只有 signal() 函数不可以,会导致进程终止!但可以用并不是说没有问题!  
   
 
有些 CRT 的函数象 malloc(),   fopen(),   _open(),   strtok(),   ctime(),   localtime() 等函数需要专门的线程局部存储的数据块,这个数据块通常需要在创建线程的时候就建立,如果使用 CreateThread ,这个数据块就没有建立,然后会怎样呢?在这样的线程中还是可以使用这些函数而且没有出错,实际上函数发现这个数据块的指针为空时,会自己建立一个,然后将其与线程联系在一起,这意味着如果你用 CreateThread 来创建线程,然后使用这样的函数,会有一块内存在不知不觉中创建,遗憾的是,这些函数并不将其删除,而 CreateThread ExitThread 也无法知道这件事,于是就会有 Memory   Leak ,在线程频繁启动的软件中 ( 比如某些服务器软件 ) ,迟早会让系统的内存资源耗尽!  
   
  _beginthreadex(
内部也调用 CreateThread) _endthreadex 就对这个内存块做了处理,所以没有问题! ( 不会有人故意用 CreateThread 创建然后用 _endthreadex 终止吧,而且线程的终止最好不要显式的调用终止函数,自然退出最好! )  
   
 
谈到 Handle 的问题, _beginthread 的对应函数 _endthread 自动的调用了 CloseHandle ,而 _beginthreadex 的对应函数 _endthreadex 则没有,所以 CloseHandle 无论如何都是要调用的不过 _endthread 可以帮你执行自己不必写,其他两种就需要自己写! (Jeffrey   Richter 强烈推荐尽量不用显式的终止函数,用自然退出的方式,自然退出当然就一定要自己写 CloseHandle)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值