C++多线程——

C++多线程——

1.函数原型及参数说明

unsigned long _beginthread(

void(_cdecl *start_address)(void *), //声明为void (*start_address)(void *)形式

unsigned stack_size, //是线程堆栈大小,一般默认为0

void *arglist //向线程传递的参数,一般为结构体

);

unsigned long _beginthreadex( //推荐使用

void *security, //安全属性,NULL表示默认安全性

unsigned stack_size, //是线程堆栈大小,一般默认为0

unsigned(_stdcall *start_address)(void *), //声明为unsigned(*start_address)(void *)形式

void *argilist, //向线程传递的参数,一般为结构体

unsigned initflag, //新线程的初始状态,0表示立即执行,CREATE_SUSPEND表示创建后挂起。

unsigned *thrdaddr //该变量存放线程标识符,它是CreateThread函数中的线程ID。

); //创建成功条件下的将线程句柄转化为unsigned long型返回,创建失败条件下返回0线程结束:

//释放线程空间、释放线程TLS空间、调用ExiteThread结束线程。

void _endthread(void);

// retval:设定的线程结束码,与ExiteThread函数的参数功能一样,

//其实这个函数释放线程TLS空间,再调用ExiteThread函数,但没有释放线程空间。

void _endthreadex(unsigned retval); 可以显示的调用这两个函数来结束线程。系统从线程启动函数返回时,也会自动调用相应的结束线程函数,收回分配给线程的资源。

两组函数都是用来创建和结束线程的。这两对函数的不同点如下:

(1)从形式上开,_beginthreadex()更像CreateThread()。_beginthreadex()比_beginthread()多3个参数:intiflag,security和threadaddr。

(2)两种创建方式的线程函数不同。_beginthreadex()的线程函数必须调用_stdcall调用方式,而且必须返回一个unsigned int型的退出码。

(3)_beginthreadex()在创建线程失败时返回0,而_beginthread()在创建线程失败时返回-1。这一点是在检查返回结果是必须注意的。

(4)如果是调用_beginthread()创建线程,并相应地调用_endthread()结束线程时,系统自动关闭线程句柄;而调用_beginthreadx()创建线程,并相应地调用_endthreadx()结束线程时,系统不能自动关闭线程句柄。因此调用_beginthreadx()创建线程还需程序员自己关闭线程句柄,以清除线程的地址空间。

下面,同样根据上一节的代码示例采用_beginthreadex来实现,实现代码如下:

#include

#include

#include

using namespace std;

typedef struct _STRUCT_DATA_

{

int id; //用于标识出票id

int tickets;

}_DATA,*_pDATA;

CRITICAL_SECTION g_cs;

unsigned __stdcall Fun1Proc(LPVOID lpParam);

unsigned __stdcall Fun2Proc(LPVOID lpParam);

void main()

{

HANDLE hThread[2] = {NULL,NULL};

unsigned threadid[2] = {0};

_DATA stru_data;

stru_data.id = 0;

stru_data.tickets = 100;

hThread[0] = (HANDLE)_beginthreadex(NULL,0,Fun1Proc,&stru_data,0,&threadid[0]);

hThread[1] = (HANDLE)_beginthreadex(NULL,0,Fun2Proc,&stru_data,0,&threadid[1]);

InitializeCriticalSection(&g_cs);

Sleep(4000);

LeaveCriticalSection(&g_cs);

}

unsigned __stdcall Fun1Proc(LPVOID lpParam)

{

_pDATA data = (_pDATA)lpParam;

while(TRUE)

{

EnterCriticalSection(&g_cs);

if (data->tickets>0)

{

Sleep(1);

cout<<"id: "<id++<

cout<<"thread1 sell<< ticket: "<tickets--<

LeaveCriticalSection(&g_cs);

}

else

{

LeaveCriticalSection(&g_cs);

break;

}

}

return 0;

}

unsigned __stdcall Fun2Proc(LPVOID lpParam)

{

_pDATA data = (_pDATA)lpParam;

while(TRUE)

{

EnterCriticalSection(&g_cs);

if (data->tickets>0)

{

Sleep(1);

cout<<"id: "<id++<

cout<<"thread2 sell ticket: "<tickets--<

LeaveCriticalSection(&g_cs);

}

else

{

LeaveCriticalSection(&g_cs);

break;

}

}

return 0;

}

猜你喜欢

泰国清迈落地签办理流程及所需材料
中信精彩365

泰国清迈落地签办理流程及所需材料

📅 09-19 ❤️ 746
大鱼海棠:椿最爱的是鲲还是湫?原来我们都闹了一个大乌龙!
重庆至邛崃直达动车抵达邛崃站,曾经“最远的你”,成为“最近的爱”
电信流量卡在农村信号好吗,电信流量卡信号稳定性实测
京东违规申诉要多久?怎么申诉?
中信精彩365

京东违规申诉要多久?怎么申诉?

📅 07-04 ❤️ 627
速速看!欧司朗好还是飞利浦好
365bet官方

速速看!欧司朗好还是飞利浦好

📅 09-02 ❤️ 348
单良的成语,形容凭良心做事的成语
中信精彩365

单良的成语,形容凭良心做事的成语

📅 06-29 ❤️ 605
民间实用的入殓忌讳与犯重丧日和三丧日查阅方法
方舟渡渡鸟蛋饲料怎么做
365bet备用线路

方舟渡渡鸟蛋饲料怎么做

📅 10-27 ❤️ 23