多线程第一篇:使用_beginthreadex创建线程
2013-12-15 08:57
591 查看
我们先来了解一下线程的相关函数:
CreateThread函数:
第二个参数是用于新线程的初始堆栈大小,默认值为0。在任何情况下,Windows根据需要动态延长堆栈的大小。
第三个参数是指向线程函数的指标。函数名称没有限制,但是必须以下列形式声明:
DWORD WINAPI ThreadProc (PVOID pParam) ;
第四个参数为传递给ThreadProc的参数。这样主线程和从属线程就可以共享数据。
第五个参数通常为0,但当建立的线程不马上执行时为旗标CREATE_SUSPENDED。线程将暂停直到呼叫ResumeThread来恢复线程的执行为止。
第六个参数是一个指标,指向接受执行绪ID值的变量。
WaitForSingleObject:等待一个object触发,参数为object的句柄
第二个参数为最长等待的时间,以毫秒为单位,如传入5000就表示5秒,传入0就立即返回,传入INFINITE表示无限等待。即返回,传入INFINITE表示无限等待。
函数返回值:
WAIT_OBJECT_0:在指定的时间内对象被触发,函数返回WAIT_OBJECT_0。
WAIT_TIMEOUT:超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。
WAIT_FAILED:传入参数有错误将返回WAIT_FAILED
_beginthreadex()和CreateThread参数是一样的,一般来讲在创建线程的时候尽量要用_beginthreadex(),我们来看看原因:
由于标准c程序库中有许多全局变量,当一个线程改变全局变量的时候会影响到其他线程,或者整个进程,例如c语言中的errno.
为了解决这个问题,Windows操作系统提供了这样的一种解决方案——每个线程都将拥有自己专用的一块内存区域来供标准C运行库中所有有需要的函数使用。而且这块内存区域的创建就是由C/C++运行库函数_beginthreadex()来负责的。
_beginthreadex()函数在创建新线程时会分配并初始化一个_tiddata块。这个_tiddata块自然是用来存放一些需要线程独享的数据。事实上新线程运行时会首先将_tiddata块与自己进一步关联起来。然后新线程调用标准C运行库函数如strtok()时就会先取得_tiddata块的地址再将需要保护的数据存入_tiddata块中。这样每个线程就只会访问和修改自己的数据而不会去篡改其它线程的数据了。因此,如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread().
(-----来自http://blog.csdn.net/morewindows/article/details/7421759)
注意:
(1)C++主线程终止时,同时也会终止所有主线程创建的子线程,不管子线程有没有执行完毕。
(2)如果某线程挂起,然后有调用WaitForSingleObject等待该线程,就会导致死锁。
( 3 ) 线程执行时候,事件处于未触发,执行完毕后自动设为触发状态.
[align=left] [/align]
从这幅图中可以看出线程之间的竞争,造成线程中的输出被打断.
参考了网上好多博客例子,只有一小部分是自己总结的.
大多数来自博客:http://blog.csdn.net/morewindows/article/details/7421759
CreateThread函数:
HANDLE WINAPI CreateThread ( _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes , // pointer to security attributes _In_ SIZE_T dwStackSize, // initial thread stack size _In_ LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function _In_opt_ LPVOID lpParameter, // argument for new thread _In_ DWORD dwCreationFlags, // creation flags _Out_opt_ LPDWORD lpThreadId // pointer to receive thread ID );第一个参数是指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL。
第二个参数是用于新线程的初始堆栈大小,默认值为0。在任何情况下,Windows根据需要动态延长堆栈的大小。
第三个参数是指向线程函数的指标。函数名称没有限制,但是必须以下列形式声明:
DWORD WINAPI ThreadProc (PVOID pParam) ;
第四个参数为传递给ThreadProc的参数。这样主线程和从属线程就可以共享数据。
第五个参数通常为0,但当建立的线程不马上执行时为旗标CREATE_SUSPENDED。线程将暂停直到呼叫ResumeThread来恢复线程的执行为止。
第六个参数是一个指标,指向接受执行绪ID值的变量。
WaitForSingleObject:等待一个object触发,参数为object的句柄
DWORD WINAPI WaitForSingleObject( _In_ HANDLE hHandle, _In_ DWORD dwMilliseconds );第一个参数为要等待的内核对象。
第二个参数为最长等待的时间,以毫秒为单位,如传入5000就表示5秒,传入0就立即返回,传入INFINITE表示无限等待。即返回,传入INFINITE表示无限等待。
函数返回值:
WAIT_OBJECT_0:在指定的时间内对象被触发,函数返回WAIT_OBJECT_0。
WAIT_TIMEOUT:超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。
WAIT_FAILED:传入参数有错误将返回WAIT_FAILED
_beginthreadex()和CreateThread参数是一样的,一般来讲在创建线程的时候尽量要用_beginthreadex(),我们来看看原因:
由于标准c程序库中有许多全局变量,当一个线程改变全局变量的时候会影响到其他线程,或者整个进程,例如c语言中的errno.
为了解决这个问题,Windows操作系统提供了这样的一种解决方案——每个线程都将拥有自己专用的一块内存区域来供标准C运行库中所有有需要的函数使用。而且这块内存区域的创建就是由C/C++运行库函数_beginthreadex()来负责的。
_beginthreadex()函数在创建新线程时会分配并初始化一个_tiddata块。这个_tiddata块自然是用来存放一些需要线程独享的数据。事实上新线程运行时会首先将_tiddata块与自己进一步关联起来。然后新线程调用标准C运行库函数如strtok()时就会先取得_tiddata块的地址再将需要保护的数据存入_tiddata块中。这样每个线程就只会访问和修改自己的数据而不会去篡改其它线程的数据了。因此,如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread().
(-----来自http://blog.csdn.net/morewindows/article/details/7421759)
注意:
(1)C++主线程终止时,同时也会终止所有主线程创建的子线程,不管子线程有没有执行完毕。
(2)如果某线程挂起,然后有调用WaitForSingleObject等待该线程,就会导致死锁。
( 3 ) 线程执行时候,事件处于未触发,执行完毕后自动设为触发状态.
#include <iostream> #include <windows.h> #include <process.h> unsigned int __stdcall ThreadFun(LPVOID ) { std::cout<< "子线程ID:" <<GetCurrentThreadId()<< std::endl ; return 0; } int main () { const int thread_num = 10; HANDLE handle[thread_num ]; for ( int i = 0 ; i<10; ++i ){ handle[i ] = (HANDLE) _beginthreadex(NULL ,0,ThreadFun, NULL,0,NULL ); } //HANDLE handle = CreateThread(NULL,0,ThreadFun,NULL,0,NULL); //WaitForSingleObject(handle,INFINITE); WaitForMultipleObjects( thread_num,handle ,true,INFINITE); //为了防止子线程没有执行就结束了. return 0; }
[align=left] [/align]
从这幅图中可以看出线程之间的竞争,造成线程中的输出被打断.
参考了网上好多博客例子,只有一小部分是自己总结的.
大多数来自博客:http://blog.csdn.net/morewindows/article/details/7421759
相关文章推荐
- 使用_beginThreadex创建多线程(C语言版多线程)
- 在类中使用_beginthreadex函数创建线程并访问该类中的数据成员
- 使用_beginThreadex创建多线程(C语言版多线程)
- 使用_beginthreadex 创建线程并实现多线程同步
- 使用_beginThreadex创建多线程(C语言版多线程)
- _beginThreadex创建多线程
- 用_beginthreadex创建线程
- c#中使用多线程访问winform中控件的若干问题 解决线程间操作无效: 从不是创建控件的线程访问它
- C++多线程实例(_beginThreadex创建多线程)
- 多线程开发要点1:如何使用类的成员函数创建线程
- (转)为什么要用C运行时库的_beginthreadex代替操作系统的CreateThread来创建线程?
- 初学Java多线程:使用Runnable接口创建线程
- _beginThreadex创建多线程解读
- _beginThreadex创建多线程解读
- C# 多线程开发 1:使用 Thread 类创建与启动线程
- 关于多线程创建时CreateThread和_beginthreadex的区别
- _beginThreadex创建多线程解读
- _beginthreadex创建线程
- C++多线程实例(_beginThreadex创建多线程)
- _beginThreadex创建多线程解读