多线程学习笔记之初始_beginthreadex()
2016-03-14 22:55
211 查看
最近有点闲,于是想探究下多线程的使用,先是研究的windows下的多线程,在此记录笔记。通过上网搜索多线程的知识,发现windows下创建多线程的函数有CreateThread()和_beginthreadex()。了解了这两个函数的区别,都推荐使用_beginthreadex()函数而不是CreateThread(),主要是为了在多线程中使用c运行时库。标准c库实现于1970年代,那时还没有多线程技术,c运行时库也就不支持多线程技术,比如原来的将errno置出错信息的编程方法运用在多线程中就不适合了。windows给出的解决方法就是为每一个线程在内存分配内存块,线程的相关数据代码存放在各自的内存块中,各个线程使用和修改各自的内存块,就不会互相影响了。
_beginthreadex()函数在msdn中的定义如下:
函数说明:
第一个参数表示线程内核对象的安全属性,一般传入NULL表示使用默认设置(设置为NULL,线程句柄无法被子线程继承)。
第二个参数表示线程栈空间大小。传入0表示使用默认大小(1MB)。
第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
第四个参数是传给线程函数的参数。
第五个参数指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。
第六个参数将返回线程的ID号,传入NULL表示不需要返回该线程ID号。
_beginthreadex()函数使用如下:
上边的函数是不带参数的,如果带参数怎么办呢,可以给线程函数传递参数,如下:
这就是我最近关于多线程的一些实践,此外,还有些个人观点:
(1)首先判断出程序中耗时的部分,对耗时的地方用多线程进行处理。
(2)创建几个线程,不宜过多,也不宜过少,最好跟计算机的核数相同。
(3)多个线程中,有快有慢,如果快的用很久时间等待慢的线程运行完,那多线程就没太大意义,劲量使多个线程的运行时间差不多。
(4)要注意线程的同步问题。
_beginthreadex()函数在msdn中的定义如下:
uintptr_t _beginthreadex( // NATIVE CODE void *security, unsigned stack_size, unsigned ( __stdcall *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr );
函数说明:
第一个参数表示线程内核对象的安全属性,一般传入NULL表示使用默认设置(设置为NULL,线程句柄无法被子线程继承)。
第二个参数表示线程栈空间大小。传入0表示使用默认大小(1MB)。
第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
第四个参数是传给线程函数的参数。
第五个参数指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。
第六个参数将返回线程的ID号,传入NULL表示不需要返回该线程ID号。
_beginthreadex()函数使用如下:
// MultiThread.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <process.h> //包含_beginthreadex()的头文件 #include <windows.h> //句柄头文件 using namespace std; unsigned __stdcall threadFun(void *) //线程调用函数 { for (int i=0;i<10;++i) { cout<<i<<" "; } cout<<endl; return 1; } int _tmain(int argc, _TCHAR* argv[]) { unsigned int thID1; //线程ID号 HANDLE hth1; //线程句柄 hth1 = (HANDLE)_beginthreadex(NULL,0,threadFun,NULL,0,&thID1); WaitForSingleObject(hth1,INFINITE); //等待线程运行结束 DWORD exitCode1; GetExitCodeThread(hth1,&exitCode1); //获得线程的推出码 cout<<"exitcode: "<<exitCode1<<" "<<endl; cout<<"ID: "<<thID1<<" "<<endl; }结果如下:
上边的函数是不带参数的,如果带参数怎么办呢,可以给线程函数传递参数,如下:
<span style="font-size:18px;">// MultiThread.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <process.h> //包含_beginthreadex()的头文件 #include <windows.h> //句柄头文件 using namespace std; struct Arg //参数结构体 { double d_; string str_; Arg(double dd,string ss):d_(dd),str_(ss){} }; unsigned __stdcall threadFun(void *) //线程调用函数 { for (int i=0;i<10;++i) { cout<<i<<" "; } cout<<endl; return 1; } unsigned __stdcall threadFunArg(void *arglist) //线程调用函数 通过结构体来传入多个参数 { cout<<endl; Arg *p = (Arg*)arglist; //反解输入参数 cout<<p->d_<<" "<<p->str_<<endl; return 2; } int _tmain(int argc, _TCHAR* argv[]) { unsigned int thID1,thID2; HANDLE hth1,hth2; Arg arg(3.14,"hello world!"); hth1 = (HANDLE)_beginthreadex(NULL,0,threadFun,NULL,0,&thID1); //创建两个线程 hth2 = (HANDLE)_beginthreadex(NULL,0,threadFunArg,&arg,0,&thID2); WaitForSingleObject(hth1,INFINITE); //等待线程运行结束 WaitForSingleObject(hth2,INFINITE); DWORD exitCode1,exitCode2; GetExitCodeThread(hth1,&exitCode1); //获得线程的退出码 GetExitCodeThread(hth2,&exitCode2); cout<<"exitcode: "<<exitCode1<<" "<<exitCode2<<endl; cout<<"ID: "<<thID1<<" "<<thID2<<endl; }</span>
这就是我最近关于多线程的一些实践,此外,还有些个人观点:
(1)首先判断出程序中耗时的部分,对耗时的地方用多线程进行处理。
(2)创建几个线程,不宜过多,也不宜过少,最好跟计算机的核数相同。
(3)多个线程中,有快有慢,如果快的用很久时间等待慢的线程运行完,那多线程就没太大意义,劲量使多个线程的运行时间差不多。
(4)要注意线程的同步问题。
相关文章推荐
- 1.3一个MFC多文档程序编写总结
- 工厂方法模式
- Hook任务栏时钟窗口(原理其实很简单,就是注入DLL到时钟窗口进程(explorer.exe))
- Java开发中的23种设计模式详解
- 回溯算法之N皇后问题
- Servlet的生命周期
- MAVEN依赖
- numpy中的tile函数
- 浅谈Javaweb经典三层架构和MVC框架模式
- java 结构型模式
- GitHub简单使用
- Hessian——轻量级远程调用方案
- bzoj 1816: [Cqoi2010]扑克牌
- 生成格雷码
- Android Framework 记录之一
- Editplus最佳配色方案
- CLOSE_WAIT状态的原因与解决方法
- LeetCode总结
- 位图的简单处理
- mac下tomcat的安装与配置