当前位置: 首页 > news >正文

C++中的多线程

1.每个进程至少包含一个执行线程,称之为主线程,再由主线程创建多个子线程。c++中没有内建的多线程的支持, 是因为效率、控制以及c++适用的应用程序的范围,但允许你直接使用操作系统提供的多线程支持。由于c++不跨平台,所以如果有内建的多线程支持的话C++就只能使用在支持多线程的环境中。

2.为了使用Windows多线程函数,需要加入<Windows.h>头文件,用CreateThread来创建一个线程。

HANDLE CreateThread(//若创建成功则返回一个句柄,失败则返回NULL,通过调用CloseHandle()来结束线程,否则它随着父线程结束LPSECURITY_ATTRIBUTES  secAttr,//描述线程安全属性的指针,若为NULL则使用默认的安全描述符SIZE_T                 stackSize,//每个线程都有自己的堆栈,stackSize就是按字节指定这个堆栈的大小,若为0则与创建它的线程的大小一样LPTHREAD_START_ROUTINE ThreadFunc,//线程所执行的函数的地址,而这个函数的参数下面的params传入LPVOID                 param,DWORD                  flags,//确定线程的执行状态,为0则立即执行,为CREATE_SUSPEND则以挂起状态创建并等待执行,通过ResumeThread()来开始执行LPDWORD                threadId//与线程有关的标识符以threadID所指向的长整型返回
);
线程可以用下面的方式来手动结束:

BOOL TerminateThread(HANDLE hThread,//将要终止的线程的句柄DWORD  status//终止状态
);
VOID  ExitThread(DWORD status//终止状态
);
但我们不会使用CreateThread()和ExitThread()来创建并终止线程,因为在VC中使用这两个函数会导致内存泄漏。Visual C++用_beginthreadex()和_endthreadex()来取代CreateThread()和Exit Thread()函数。
uintptr_t _beginthreadex(void *setAttr,  unsigned stacksize,  unsigned ( __clrcall *threadFunc )( void * ),  void *param,  unsigned flags,  unsigned *threadID   
);  
参数的使用和CreateThread()一样,unitptr_t指定了可以拥有指针或者句柄的VC类型。
void   _endthreadex(   unsigned  status );//停止线程并返回status中的退出代码。 
线程的挂起和恢复:
DWORD SuspendThread(HANDLE hThread);
DWORD ResumeThread(HANDLE hThread);
线程都有一个挂起计数,计数为0则不会挂起线程,为非0则会挂起线程。调用 SuspendThread会增加计数,ResumeThread会减少计数,挂起的线程只有计数减为0时才会恢复,所以要恢复一个线程,SuspendThread与ResumeThread的调用次数应该相等。两个函数返回的是线程先前的挂起计数。
改变线程的优先级:线程的优先级由进程总体的优先级和相对于这个优先级类别的各个线程的优先级这两个共同决定。
1.优先级类别:
在默认情况下,进程具有普通的优先级类别,大多数程序在其执行的声明周期内保持这个普通的优先级类别。尽管在本章的示例中没有改变优先级类别,但是为了完整起见,在此给出了线程优先级类别的简单概况。优先级从高到低分别为:
REALTIME_PRIORITY_CLASS
HIGH_PRIORITY_CLASS
ABOVE_NORMAL_PRIORITY_CLASS
NORMAL_PRIORITY_CLASS
BELOW_NORMAL_PRIORITY_CLASS
IDLE_PRIORITY_CLASS
在默认情况下,程序的优先级类别为NORMAL_PRIORITY_CLASS。通常,您不需要改变程序的优先级类别。事实上,改变进程的优先级类别对于整个计算机系统的性能会有负面的影响。例如,如果您将一个程序的优先级类别增加到REALTIME_PRIORITY_CLASS,它就会支配CPU。对于某些特殊的应用程序,可能需要增加应用程序的优先级类别,但通常并不需要。如前所述,本章的应用程序没有改变优先级类别。

当确实需要改变程序的优先级类别时,可以调用SetPriorityClass()。可以调用GetPriorityClass()来获取当前的优先级类别。这两个函数的原型如下:

DWORD GetPriorityClass(HANDLE hApp);

BOOL SetPriorityClass(HANDLE hApp, DWORD priority);

在此,hApp是进程的句柄。GetPriorityClass()返回应用程序的优先级类别,如果失败的话,返回0。对于SetPriorityClass(),priority指定了进程的新优先级类别。

2.线程优先级:
对于给定的优先级类别,各个线程的优先级确定了它在进程内接收的CPU时间的多少。当线程第一次创建时,它具有普通的优先级,但是你可以改
变线程的优先级。
可以通过调用GetThreadPriority()来获取线程的优先级设置。可以使用SetThreadPriority()来增加或者减小线程的优先级。
BOOL SetThreadPriority(HANDLE  hThread , int  priority );
int GetThreadPriority(HANDLE  hThread );
hThread 是线程的句柄。对于SetThreadPriority(), priority 是新的优先级设置。如果发生错误,则返回值为0;否则,返回非0 值。
GetThreadPriority()会返回当前的优先级设置。优先级设置按照从高到低的顺序如下:

线程优先级

THREAD_PRIORITY_TIME_CRITICAL

15

THREAD_PRIORITY_HIGHEST

2

THREAD_PRIORITY_ABOVE_NORMAL

1

THREAD_PRIORITY_NORMAL

0

THREAD_PRIORITY_BELOW_NORMAL

-1

THREAD_PRIORITY_LOWEST

-2

THREAD_PRIORITY_IDLE

-15

这些值相对于进程的优先级类别或增或减。通过组合进程的优先级类别和线程的优先级Windows向应用程序提供了31个不同的优先级设置的支持。

如果有错误发生,则GetThreadPriority()返回THREAD_PRIORITY_ERROR_RETURN。在大多数情况下,如果线程具有普通的优先级类别,

那么可以随意地改变它的优先级设置,而不必担心会给整个系统的性能带来灾难性的影响。您将会看到,在下面部分开发的线程控制面板中,

可以改变进程内线程的优先级设置(但是不能改变优先级类别)。

获取主线程的句柄:

HANDLE GetCurrentThread();

同步:可以使用互斥企业同步线程,互斥在给定的时间只允许一个线程访问某个资源。创建互斥信号量如下:

HANDLE  CreateMutex(LPSECURITY_ATTRIBUTES secAttr,//安全指针,为NULL则使用默认的指针BOOL                  acquire,//需要互斥体的控制的话则为true,否则为falseLPCTSTR               lpName//指向一个字符串,这个字符串是互斥对象的名字,有了名字之后多个就可以用这个名字取控制多个线程,若为NULL
则信号量被限制在一个线程内
);
当信号量不需要的时候用CloseHandle()关闭互斥信号量句柄。信号量可以和下面两个函数一起使用:
DWORD WaitForSingleObject(//等待一个同步对象,直到这个对象可以使用或者超时之后才会返回HANDLE hObject,//互斥体的句柄DWORD  dwMilliseconds//以毫秒为单位的等待时间,为INFINITE则无限等待
);
函数执行成功则返回WAIT_OBJECT_0,若超时则返回WAIT_TIMEOUT。

BOOL ReleaseMutex(//释放互斥体并允许其他线程获取它HANDLE hMutex
);

二者的使用如下:
if(WaitForSingleObject(hMutex,10000)==WAIT_TIMEOUT){//WaitForSingleObject(hMutex,10000)即为进行互斥操作,超时的时候返回WAIT_TIMEOUT,此时抛出异常返回。
//handle time-out erroe
}
//access the resource

ReleaseMutex(hMutex);

http://www.xdnf.cn/news/811099.html

相关文章:

  • CGI与FastCGI
  • ansys fluent udf manual 下载_【FLUENT】Fluent 2020R1中文版(启动方法)
  • C语言基础知识(适合初学者)
  • 10 常见网站安全攻击手段及防御方法
  • 花指令简析
  • PHP包含文件函数include、include_once、require、require_once区别总结
  • 【学习笔记】AD中PCB泪滴设计
  • ms08-067漏洞复现
  • 半监督之mixmatch
  • SHFileOperation复制文件夹、文件用法
  • 半透明AlphaBlend
  • Android移动应用开发教程①
  • Html5游戏框架createJs组件--EaselJS(一)
  • [转]FastDb介绍
  • 位运算的基础知识
  • C++图像缩放(StretchBlt,StretchDIBits,双线性内插法)
  • 软件测试面试及笔试题
  • 【Dom4j】Dom4j完整教程详解
  • 盘点日本人最常用的50个网站
  • tp-link无线网卡linux下的驱动,Ubuntu14下安装无线网卡驱动(TP-LINK TL-WN823N)
  • Visual Studio2010 简体中文含MSDN版本下载地址
  • You-Get 就是这么强势!
  • android的m、mm、mmm编译命令的使用
  • 什么是公网、私网、内网、外网?
  • 使用FileZilla等软件搭建ftp服务器
  • android高级面试题(二)
  • 校园后勤设备保修维护管理系统
  • 递推算法题:令人费解的开关『拉灯』
  • 安卓开发中JDK、SDK、NDK、ADT、ANT等概念作用解释
  • linux命令行怎么结束进程,linux结束进程命令