本文主要参考以下链接,感谢前辈的分享。

秒杀多线程    多线程总结

先来一个简单的例子,展示如何创建一个线程

#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;
unsigned Counter;unsigned __stdcall SecondThreadFunc(PVOID pArguments)
{printf("In second thread...\n");while (Counter < 1000000)Counter++;printf("done\n");_endthreadex(0);//如果把 printf("done\n");放在此段代码之后,则不会执行return 0;
}int main()
{HANDLE hThread;unsigned threadID;// Create the second thread.  hThread = (HANDLE)_beginthreadex(NULL, 0, &SecondThreadFunc, NULL, 0, &threadID);//创建线程函数WaitForSingleObject(hThread, INFINITE);//注意这个函数的使用printf("Counter should be 1000000; it is-> %d\n", Counter);cout << threadID << endl;// Destroy the thread object.  CloseHandle(hThread);//个人感觉仅仅关闭了句柄,并没有关闭线程资源,也即线程还在跑system("pause");return 0;
}

WaitForSingleObject 函数介绍

WaitForSingleObject(hThread, INFINITE); 等待hThread这个线程发出信号,才会执行接下来的代码。INFINITE表示无期限等待,直到hThread线程发出信号。
WaitForSingleObject(hThread, 10); 表示等待10ms,10ms内发出信号,则返回WAIT_OBJECT_0,超过时间则返回WAIT_TIMEOUT。如果该函数失败,返回WAIT_FAILED。

可以通过下面的代码来判断:

DWORD dw = WaitForSingleObject(hProcess, 5000); //等待一个进程结束
switch (dw)
{
   case WAIT_OBJECT_0:
      // hProcess所代表的进程在5秒内结束
       break;

case WAIT_TIMEOUT:
      // 等待时间超过5秒
       break;

case WAIT_FAILED:
      // 函数调用失败,比如传递了一个无效的句柄
       break;
}

还可以使用WaitForMulitpleObjects函数来等待多个内核对象变为已通知状态:

DWORD WaitForMultipleObjects(

DWORD dwCount,     //等待的内核对象个数
   CONST HANDLE* phObjects,     //一个存放被等待的内核对象句柄的数组
   BOOL bWaitAll,     //是否等到所有内核对象为已通知状态后才返回
   DWORD dwMilliseconds);     //等待时间
  该函数的第一个参数指明等待的内核对象的个数,可以是0到MAXIMUM_WAIT_OBJECTS(64)中的一个值。phObjects参数是一个存放等待的内核对象句柄的数组。bWaitAll参数如果为TRUE,则只有当等待的所有内核对象为已通知状态时函数才返回,如果为FALSE,则只要一个内核对象为已通知状态,则该函数返回。第四个参数和WaitForSingleObject中的dwMilliseconds参数类似。

临界区和事件 解决线程同步和互斥问题 的例子

#include<iostream>
#include <process.h>
#include <windows.h>
using namespace  std;long g_nNum;
unsigned int __stdcall Fun(PVOID pPM);
const int THREAD_NUM = 10;
//事件与关键段
HANDLE  g_hThreadEvent;
CRITICAL_SECTION g_csThreadCode;
int main()
{cout << "      经典线程同步 事件Event\n" << endl;//初始化事件和关键段 自动置位,初始无触发的匿名事件  g_hThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);InitializeCriticalSection(&g_csThreadCode);HANDLE  handle[THREAD_NUM];g_nNum = 0;int i = 0;while (i < THREAD_NUM){handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);WaitForSingleObject(g_hThreadEvent, INFINITE); //等待事件被触发  i++;}WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);//销毁事件和关键段  CloseHandle(g_hThreadEvent);DeleteCriticalSection(&g_csThreadCode);system("pause");return 0;
}
unsigned int __stdcall Fun(PVOID pPM)
{int nThreadNum = *(int *)pPM;SetEvent(g_hThreadEvent); //触发事件  Sleep(50);//some work should to do  EnterCriticalSection(&g_csThreadCode);g_nNum++;Sleep(0);//some work should to do  cout << "线程编号为:" << nThreadNum << "全局资源为:" << g_nNum << endl;LeaveCriticalSection(&g_csThreadCode);return 0;
}

关键段CRITICAL_SECTION一共就六个函数,使用很是方便。如下所示为常用的四个函数

函数功能:初始化

函数原型:void InitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

函数说明:定义关键段变量后必须先初始化。

函数功能:销毁

函数原型:void DeleteCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

函数说明:用完之后记得销毁。

函数功能:进入关键区域

函数原型:void EnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

函数说明:系统保证各线程互斥的进入关键区域。

函数功能:离开关关键区域

函数原型:void LeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

事件Event实际上是个内核对象,它的使用非常方便。下面列出一些常用的函数。(CreateEvent,SetEvent,ResetEvent)

CreateEvent

函数功能:创建事件

函数原型:

HANDLECreateEvent(

LPSECURITY_ATTRIBUTESlpEventAttributes,

BOOLbManualReset,

BOOLbInitialState,

LPCTSTRlpName

);

函数说明:

第一个参数表示安全控制,一般直接传入NULL。

第二个参数确定事件是手动置位还是自动置位,传入TRUE表示手动置位,传入FALSE表示自动置位。如果为自动置位,则对该事件调用WaitForSingleObject()后会自动调用ResetEvent()使事件变成未触发状态。打个小小比方,手动置位事件相当于教室门,教室门一旦打开(被触发),所以有人都可以进入直到老师去关上教室门(事件变成未触发)。自动置位事件就相当于医院里拍X光的房间门,门打开后只能进入一个人,这个人进去后会将门关上,其它人不能进入除非门重新被打开(事件重新被触发)。

第三个参数表示事件的初始状态,传入TRUR表示已触发。

第四个参数表示事件的名称,传入NULL表示匿名事件。

SetEvent

函数功能:触发事件

函数原型:BOOLSetEvent(HANDLEhEvent);

函数说明:每次触发后,必有一个或多个处于等待状态下的线程变成可调度状态。

ResetEvent

函数功能:将事件设为末触发

函数原型:BOOLResetEvent(HANDLEhEvent);

最后一个事件的清理与销毁

由于事件是内核对象,因此使用CloseHandle()就可以完成清理与销毁了。

C++ 多线程学习总结相关推荐

  1. Java多线程学习处理高并发问题

    在程序的应用程序中,用户或请求的数量达到一定数量,并且无法避免并发请求.由于对接口的每次调用都必须在返回时终止,因此,如果接口的业务相对复杂,则可能会有多个用户.调用接口时,该用户将冻结. 以下内容将 ...

  2. C#多线程学习(四) 多线程的自动管理(线程池) (转载系列)——继续搜索引擎研究...

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  3. 艾伟:C#多线程学习(六) 互斥对象

    本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习( ...

  4. C# 多线程学习总结

    C#多线程学习(一) 多线程的相关概念 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程? 线程是 ...

  5. C#多线程学习(二) 如何操纵一个线程

    C#多线程学习(二) 如何操纵一个线程 原文链接:http://kb.cnblogs.com/page/42529/ [1] C#多线程学习(二) 如何操纵一个线程 [2] C#多线程学习(二) 如何 ...

  6. 多线程学习-基础(四)常用函数说明:sleep-join-yield

    一.常用函数的使用 (1)Thread.sleep(long millis):在指定的毫秒内让当前正在执行的线程休眠(暂停执行),休眠时不会释放当前所持有的对象的锁. (2)join():主线程等待子 ...

  7. C#多线程学习之(五)使用定时器进行多线程的自动管理

    本文实例讲述了C#多线程学习之使用定时器进行多线程的自动管理.分享给大家供大家参考.具体分析如下: Timer类:设置一个定时器,定时执行用户指定的函数. 定时器启动后,系统将自动建立一个新的线程,执 ...

  8. java多线程学习-java.util.concurrent详解

    http://janeky.iteye.com/category/124727 java多线程学习-java.util.concurrent详解(一) Latch/Barrier 博客分类: java ...

  9. C#多线程学习(三) 生产者和消费者

    C#多线程学习(三) 生产者和消费者 原文链接:http://kb.cnblogs.com/page/42530/ 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操 ...

  10. C#多线程学习(五) 多线程的自动管理(定时器) (转载系列)——继续搜索引擎研究...

    Timer类:设置一个定时器,定时执行用户指定的函数.               定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数. 初始化一个Timer对象: Timer timer ...

最新文章

  1. sql 插入新数据 如何处理等字符_条码打印软件之如何在条码数据插入字符而不被扫描...
  2. 【Netty】Netty为什么要手动释放ByteBuf资源?
  3. 用反向传导进行分子动力学模拟并比较NN二甲基苯胺,N甲基苯胺,苯胺,硝基苯的定位效应
  4. 吕梁离石学校计算机专业在哪里,山西吕梁计算机大专学校有哪些太重技校告诉您...
  5. javascript 解密_Javascript中的AES加密和Java中的解密
  6. java学习(150):文本缓冲流
  7. java伪协议_通过伪协议解决父页面与iframe页面通信的问题
  8. python3 爬虫实战:为爬虫添加 GUI 图像界面 之 tkinter
  9. Redis中两种持久化机制RDB和AOF
  10. 《Windows 8 权威指南》——1.3 引入全新内核休眠模式,实现“瞬间开机”
  11. linux 图形化修改时区,Centos 7图形化与安装中文支持与修改时区方法
  12. 使用SecureCRT工具上传、下载文件的两种方法
  13. 在苹果系统MacOS上安装PowerDesigner16.5
  14. altium Designer布等长线、蛇形线
  15. 数据库的内连接和外连接的区别
  16. Microsoft Access 操作查询
  17. 【转】中华吸血鬼分析
  18. LNK2005错误的原因与解决
  19. 企业员工管理系统 一:项目介绍
  20. fedora16上搭建lxr-1.2.0

热门文章

  1. 2022物联网工程保研经历分享(中科院计算所、中科院软件所、中科大、南大、华中科技大学、北航、哈工大、中山大学等)
  2. sinon.js的spy、stub和mock
  3. 生活中的收支明细该如何记录
  4. 罗杰斯的创新扩散模型
  5. 理解计数排序算法的原理和实现
  6. sel2000服务器自动关闭,管家婆辉煌:轻松处理SQL 2000数据库自动停止
  7. 微信小程序搜索,搜索历史,清除搜索历史,以及点击搜索历史实现搜索功能
  8. 基于Python的招聘网站爬虫及可视化的设计与实现
  9. ANSI E1.11-2008(R2018) DMX512-A 部分翻译
  10. ubuntu16.04 安装拼音输入法