随着计算机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-金鸡独立的博客。再见!

C++多线程技术windows常用方法的更多相关文章

  1. VC中利用多线程技术实现线程之间的通信

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

  2. 基于JAVA语言的多线程技术

    1.简介 多线程技术属于操作系统范围内的知识: 进程与线程 可以这么理解,一个应用程序就是一个进程,在一个进程中包含至少一个线程:进程就是线程的容器,真正工作.处理任务的是线程. 进程是操作系统分配资 ...

  3. OS X 和iOS 中的多线程技术(上)

    OS X 和iOS 中的多线程技术(上) 本文梳理了OS X 和iOS 系统中提供的多线程技术.并且对这些技术的使用给出了一些实用的建议. 多线程的目的:通过并发执行提高 CPU 的使用效率,进而提供 ...

  4. Java中的多线程技术全面详解

    本文主要从整体上介绍Java中的多线程技术,对于一些重要的基础概念会进行相对详细的介绍,若有叙述不清晰或是不正确的地方,希望大家指出,谢谢大家:) 为什么使用多线程 并发与并行 我们知道,在单核机器上 ...

  5. 赶紧收藏!王者级别的Java多线程技术笔记,我java小菜鸡愿奉你为地表最强!

    Java多线程技术概述 介绍多线程之前要介绍线程,介绍线程则离不开进程. 首先 , 进程 :是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元: 线程:就 ...

  6. C# 多线程技术

    这节讲一下多线程(Thread)技术. 在讲线程之前,先区分一下程序,进程,线程三者的区别,大体上说,一个程序可以分为多个进程,一个进程至少由一个线程去执行,它们是层层包含的关系.我们写的程序,就是一 ...

  7. iOS多线程技术方案

    iOS多线程技术方案 目录 一.多线程简介 1.多线程的由来 2.耗时操作的模拟试验 3.进程和线程 4.多线程的概念及原理 5.多线程的优缺点和一个Tip 6.主线程 7.技术方案 二.Pthrea ...

  8. C#多线程技术总结(异步)

    我这里针对现有的C#多线程技术进行一个汇总,一是复习,二是方便索引,文章部份知识点来源于网络,非本人原创. 一.并行(异步): 1.System.Threading.Tasks命名空间下的(TPL): ...

  9. iOS开发之多线程技术

    本篇争取一篇讲清讲透,依然将通过四大方面清晰的对iOS开发中多线程的用法进行详尽的讲解: 一.什么是多线程 1)多线程执行原理 2)线程与进程 3)多线程的优缺点 二.我们为什么要用多线程编程技术 三 ...

随机推荐

  1. Android内存优化解决 资料和总结的经验分享

    在前公司做一个图片处理的应用时, 项目交付的时候,客户的手机在运行应用的时候,一直在崩溃,而这个异常就是OutOfMemory的错误,简称为OOM, 搞得我们也是极其的崩溃,最后 ,我们是通过网上搜集 ...

  2. Android 使用 Gmail 来发送邮件

    Android 使用 Gmail 来发送邮件 1. [代码]SendMail.java package org.apache.android.mail; import android.app.Acti ...

  3. Android 滑动效果高级篇(七)—— 华丽翻页效果

    By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处 之前看到像ipad上的ibook的模拟书籍翻页的特效感觉很炫,在android上也有像laputa和ireader ...

  4. Linux pipe函数

    1. 函数说明 pipe(建立管道): 1) 头文件 #include<unistd.h> 2) 定义函数: int pipe(int filedes[2]); 3) 函数说明: pipe ...

  5. SQL Server XML Path[转]

    FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作.那么以一个实例为主 ...

  6. [Effective C++ --028]避免返回handles指向对象内部成分

    假设程序涉及矩形.每个矩形由其左上角和右下角表示.为了让Rectangle对象尽可能小,可能把定义矩形的点放在一个辅助的struct内再让Rectangle去指它: class Point { // ...

  7. jgroup 概述--官方文档

    原文地址:http://www.jgroups.org/manual/html/ch01.html# Chapter 1. Overview 1.1. Channel 1.2. Building Bl ...

  8. 12096 - The SetStack Computer UVA

    Background from Wikipedia: \Set theory is a branch of mathematics created principally by the German ...

  9. python--json & pickle 模块

    用于序列化的两个模块 json,用于字符串 和 python数据类型间进行转换 pickle,用于python特有的类型 和 python的数据类型间进行转换 Json模块提供了四个功能:dumps. ...

  10. cocos2d-x lua 使用http(下载图片, POST JSON)

    cocos2d-x lua 使用http(下载图片, POST JSON) version: cocos2d-x 3.6 1.使用http post json与服务器交互 require(" ...