C++多线程技术windows常用方法

随着计算机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

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

delete HANDLE //释放指针资源
//说明:HANDLE是一个HANDLE型指针,代表释放一个线程的资源,使线程死亡

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

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

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

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

那么,关于多线程的基本C++API就讲完了,那么我要说一个关键字——volatile。它代表“易变的”,编译器不会优化使用这个关键字生命的全局变量,保证此变量完全“听你的话”。那么,就可以实现简单的线程间通讯。接着,来写一个比较简单的例程,本来是Java1234的多线程例程,现在被我改成了C++版本。请看:

//多线程抢占输出
#include <iostream>
#include <windows.h>

using namespace std;

void ThreadUser(){ //线程入口
    cout<<"子线程开始"<<"\n";
     for(int i=0;i<100;++i){ //抢占循环
        cout<<"子线程第"<<i<<"次循环抢占;"<<"\n"; //输出信息
        Sleep(100); //抢占延时
    }
    cout<<"子线程结束"<<"\n";
}

int main(){
    cout<<"主线程开始"<<"\n";
    HANDLE h; //线程句柄
    CreateThread(null,0,(LPTHREAD_START_ROUTINE)ThreadUser,null,1,0); //创建子线程
    ResumeThread(HANDLE);  //启动子线程
    for(int i=0;i<100;++i){ //抢占循环
        cout<<"主线程第"<<i<<"次循环抢占;"<<"\n"; //输出信息
        Sleep(100); //抢占延时
    }
    Sleep(1000); //等待子线程
    delete h; //回收子线程资源
    cout<<"主线程结束"<<"\n";
    system("pause");
    return 0;
}

好了,我们的多线程就先讲到这里,下次再见。

顺便说一下,我们的老朋友windows XP今天退役了,大家默哀一下吧……

欢迎继续关注BKMMSC-金鸡独立的博客。再见!

posted @ 2014-04-08 18:34  金鸡独立  阅读(18048)  评论(5编辑  收藏  举报