您的位置:首页 > 其它

多线程学习笔记之初始_beginthreadex()

2016-03-14 22:55 211 查看
最近有点闲,于是想探究下多线程的使用,先是研究的windows下的多线程,在此记录笔记。通过上网搜索多线程的知识,发现windows下创建多线程的函数有CreateThread()和_beginthreadex()。了解了这两个函数的区别,都推荐使用_beginthreadex()函数而不是CreateThread(),主要是为了在多线程中使用c运行时库。标准c库实现于1970年代,那时还没有多线程技术,c运行时库也就不支持多线程技术,比如原来的将errno置出错信息的编程方法运用在多线程中就不适合了。windows给出的解决方法就是为每一个线程在内存分配内存块,线程的相关数据代码存放在各自的内存块中,各个线程使用和修改各自的内存块,就不会互相影响了。

_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)要注意线程的同步问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: