Windows 线程创建方式的比较
2016-07-14 13:08
447 查看
进行 Windows 编程时,常需要涉及多线程编程,以下是 Windows 提供的关于创建线程的3个API。
由于工作繁忙,还未来得及编辑完本篇博客,但是基本内容已经讲清楚,如有疑问,可自行查阅 MSDN。如再有时间,将尽快补全。
__beginthread
_beginthreadex
但是,_beginthread 和 _beginthreadex 两个函数会在真正创建一个线程之前,先创建一个线程局部资源区 tiddata。
所以,如果线程中会使用到 CRT 运行时函数,最好不要使用 CreateThread 创建线程。因为,一旦CRT运行时函数发生异常,通过 GetLastError 获得错误码时,获得的可能是其他线程在使用CRT运行时函数所产生的错误。
_beginthread ,如果线程执行函数返回过快(创建函数还没有返回,线程已经执行完毕),则将导致 _beginthread 返回无效句柄。实际上,_beginthread 并不保证返回有效句柄。
所以 _beginthread 返回的句柄不能用于 WaitForSingleObject 。
注:WaitForSingleObject 是用于检测句柄状态的一个API,在此处可以用于线程同步。
_beginthreadex 可设置线程初始状态,以及是否可以继承性等安全属性。由于本函数返回的句柄 Handle 必须被调用线程关闭 CloseHandle ,所以本函数保证返回一个有效的句柄。
_beginthread 创建的线程执行函数,在 return 时,将自动调用 _endthread(也可以显示调用), 而且 _endthread 会主动 CloseHandle,
所以对于_beginthread 创建的线程句柄,不需要显示的调用 CloseHandle。
_beginthreadex 创建的线程执行函数在 return 时,将自动调用 _endthreadex(也可以显示调用), 而 _endthreadex 并不会主动调用 CloseHandle。
由 _beginthreadex 创建的线程句柄,必要由调用 _beginthreadex 的线程 CloseHandle ,以避免句柄泄露。
主动的显式调用 ExitThread、_endthread 和 _endthreadex 会导致不会调用自动C++类的析构函数,而通过 return 返回的结束线程方式会调用C++类的析构函数
所以通过 return 来结束一个线程吧。
创建线程时,_beginthread 和 _beginthreadex 都可以使用,但是 _beginthread 返回的 Handle 不能通过 WaitForSingleObject 来同步主辅线程。
因为,_beginthread 创建的线程在返回时,会主动调用 CloseHanlde ,所以,如果线程返回过快,就会导致 WaitForSingleObject 无法检测句柄状态(Handle)。
以下这段英文摘自 MSDN:
所以 WaitForSingleObject , 所以是无法检测到 由 _beginthread 返回的 Handle 的状态的。
综上所述,创建线程的时候,最好不要使用 CreateThread 和 _beginthread 。而尽量使用 _beginthreadex。
由于工作繁忙,还未来得及编辑完本篇博客,但是基本内容已经讲清楚,如有疑问,可自行查阅 MSDN。如再有时间,将尽快补全。
一、 函数原型
CreateThreadHANDLE WINAPI CreateThread( __in LPSECURITY_ATTRIBUTES lpThreadAttributes, __in SIZE_T dwStackSize, __in LPTHREAD_START_ROUTINE lpStartAddress, __in LPVOID lpParameter, __in DWORD dwCreationFlags, __out LPDWORD lpThreadId );
__beginthread
uintptr_t _beginthread( void( *start_address )( void * ), unsigned stack_size, void *arglist );
_beginthreadex
uintptr_t _beginthreadex( void *security, unsigned stack_size, unsigned ( *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr );
二、三者之间的差别
CreateThread 不会创建线程局部数据 tiddata,用于存储CRT运行时可能产生的错误 ( 存储在 errno 变量之间,对于多线程来说,是个全局共享变量,有数据竞争问题 )但是,_beginthread 和 _beginthreadex 两个函数会在真正创建一个线程之前,先创建一个线程局部资源区 tiddata。
所以,如果线程中会使用到 CRT 运行时函数,最好不要使用 CreateThread 创建线程。因为,一旦CRT运行时函数发生异常,通过 GetLastError 获得错误码时,获得的可能是其他线程在使用CRT运行时函数所产生的错误。
_beginthread ,如果线程执行函数返回过快(创建函数还没有返回,线程已经执行完毕),则将导致 _beginthread 返回无效句柄。实际上,_beginthread 并不保证返回有效句柄。
所以 _beginthread 返回的句柄不能用于 WaitForSingleObject 。
注:WaitForSingleObject 是用于检测句柄状态的一个API,在此处可以用于线程同步。
_beginthreadex 可设置线程初始状态,以及是否可以继承性等安全属性。由于本函数返回的句柄 Handle 必须被调用线程关闭 CloseHandle ,所以本函数保证返回一个有效的句柄。
_beginthread 创建的线程执行函数,在 return 时,将自动调用 _endthread(也可以显示调用), 而且 _endthread 会主动 CloseHandle,
所以对于_beginthread 创建的线程句柄,不需要显示的调用 CloseHandle。
_beginthreadex 创建的线程执行函数在 return 时,将自动调用 _endthreadex(也可以显示调用), 而 _endthreadex 并不会主动调用 CloseHandle。
由 _beginthreadex 创建的线程句柄,必要由调用 _beginthreadex 的线程 CloseHandle ,以避免句柄泄露。
主动的显式调用 ExitThread、_endthread 和 _endthreadex 会导致不会调用自动C++类的析构函数,而通过 return 返回的结束线程方式会调用C++类的析构函数
所以通过 return 来结束一个线程吧。
创建线程时,_beginthread 和 _beginthreadex 都可以使用,但是 _beginthread 返回的 Handle 不能通过 WaitForSingleObject 来同步主辅线程。
因为,_beginthread 创建的线程在返回时,会主动调用 CloseHanlde ,所以,如果线程返回过快,就会导致 WaitForSingleObject 无法检测句柄状态(Handle)。
以下这段英文摘自 MSDN:
_endthread calls CloseHandle, destroying the thread object before it can be set to the signaled state ,
所以 WaitForSingleObject , 所以是无法检测到 由 _beginthread 返回的 Handle 的状态的。
综上所述,创建线程的时候,最好不要使用 CreateThread 和 _beginthread 。而尽量使用 _beginthreadex。
相关文章推荐
- shell学习-9-if-case-for-while-until-break
- 数据库学习之————sqlite3数据库常用函数
- 二分查找算法(Java实现)
- Hibernate和IBatis对比(优缺点)
- 好记性不如烂笔头之Oracle SQL优化(1)
- 基于 CoreText 实现的高性能 UITableView
- 好记性不如烂笔头之html和css笔记
- css限制显示字数,文字长度超出部分用省略号表示
- 好记性不如烂笔头之常用javasript基础
- JAVA多线程(一)
- III(二十一)SVN
- JAVA多线程(二)
- 【个人喜好诗词之一】将进酒
- 【转】Timer还是Handler
- 腾讯优测|优社区干货精选-手Q红包后台设计!
- many-to-one各属性含义
- MATLAB经典测试图像集 Standard test image
- MATLAB经典测试图像集 Standard test image
- hibernate对象关系映射(基于注解)
- MVC学习系列4--@helper辅助方法和用户自定义HTML方法