C++多线程编程

随着计算机CPU计算能力快速提高,计算机的处理性能和并行性能力也大大提升。那么,一味使用运行时标准库的C++语言也应该开始支持多线程技术。今天,我为大家带来了C++在windows平台下的常用多线程方法。

首先我先说一下线程的状态。线程有挂起状态、执行状态、阻塞状态和等待状态,下面分别介绍:挂起状态是说线程创建后并没有直接执行或是调用函数挂起了线程。被挂起了的线程没有执行的能力,只有调用启动函数了之后才能执行。而执行状态是指在线程的时间片内,拥有CPU资源的时候,这是,线程便开始执行。阻塞状态是由于进行大量输入输出操作或发生执行错误时,线程失去执行状态,只有等待问题解除之后,线程才能进入等待状态。等待状态是指线程启动或时间片抢占失败是等待其他线程执行,在此期间,线程随时可能被执行。那么,请大家看一个流程图:

线程流程

因为C++不像Java一样需要进行跨平台优化,所以我们使用最简单的方法来实现多线程技术——windows.h中的CreateThread以及相关函数和类。首先,以如下的方式引用头文件:

#include <windows.h>

下面,我们来介绍如何创建线程,我不会向一般的教程那样上来先罗列一大堆MSDN上的函数原型,把大家弄得糊里糊涂了再讲,我首先先把函数原型翻译成中文好了:

复制代码
线程句柄 CreateThread(
                 线程安全性描述(一个结构体,一般是NULL)LPSECURITY_ATTRIBUTES  lpThreadAttributes,
                 一种数值(栈深度,一般是0)DWORD  dwStackSize,
                 启动函数(一般情况如下阐述) LPTHREAD_START_ROUTINE lpStartAddress,
                 附加参数(一般为NULL) LPVOID lpParameter,
                 运行参数(是否在创建完成后就启动线程,具体下面将)DWORD dwCreationFlags,
                 返回句柄(一般是0,或者是一个DWORD型变量的地址,别忘了&)LPDWORD lpThreadId);
复制代码

下面我就重点说一下:

//这第三个参数启动函数很重要:
 LPTHREAD_START_ROUTINE lpStartAddress
//我们一般这样写:
(LPTHREAD_START_ROUTINE) ThreadStart
//意思就是在线程启动的时候调用ThreadStart,之后他就不管了,也就是说这个函数就是线程主函数相当于main的意思。也就是说在这个函数中调用的类资源或函数资源都是属于这个线程的。除了static的存储类

还有我要说一下HANDLE这个类型,它其实是一个指针,也是CreateThread的返回值。也就是一个线程句柄,用于标示一个线程。当然,其他对于线程的操作都需要使用这个指针。如果你没有学过指针引用,还是好好复习一下*和&吧。对了还有->。我为什么要介绍HANDLE呢?因为我将要说一下倒数第二个参数——运行参数。这是实际上是一个bool类型的值,用于标示是否在创建线程后立刻执行,如果为true,也就是0,那么就会立刻执行,否则将会挂起,等待启动。那么,我们用以下方法启动线程:

DWORD ResumeThread(HANDLE hThread); //启动线程
//说明:DWORD是一个数值,代表句柄,无需关注;
//参数表示要启动的线程的句柄,也就是刚才介绍的由CreateThread返回的HANDLE

如果调用这个函数,将会启动HANDLE参数所代表的线程。下面我们看看如何挂起线程,使线程进入挂起状态:

DWORD SuspendThread(HANDLE hThread); //挂起线程
//说明:DWORD是一个整数值,代表一个句柄,无需过分关注
//参数:一个HANDLE线程指针,由CreateThread创建
//功能:挂起线程直到使用ResumeThread

挂起线程后可以进行释放以便停止线程:


 
BOOL CloseHandle(
HANDLE hThread
); //
关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。
若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成 内核对象的泄露,相当于 句柄泄露,但不同于 内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。
参数
hThread:代表一个已打开对象handle。
返回值
TRUE:执行成功;
FALSE:执行失败,可以调用GetLastError()获知失败原因。

挂起线程也可能为了等待重要操作然后再执行线程,以下函数将解除线程挂起状态,使线程进入等待状态:

DWORD ResumeThread(HANDLE hThread); //使线程脱离挂起状态
//说明:返回值也是句柄
//参数:HANDLE类型指针,表示要继续的线程,或刚创建而没有启动的线程
//注意:如果对等待状态下的线程使用本函数,可能会抛出异常或无效果,具体请见MSDN

实际上,停止一个线程还有一种方法——强行停止,但是已经不建议使用,现在都是使用挂起+delete的方法,因为使用强行停止会有很多的安全问题,但也是一个功能,所以在这里为大家介绍一下:

BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode); //强行停止线程
//说明:返回值代表是否成功
//参数:HANDLE指针代表需要结束的线程,DWORD数值代表该线程的退出值
//功能:在任何位置结束任何线程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值