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

秒杀多线程    多线程总结

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

#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. 现金奖励+实习offer!数据库大赛来了
  2. 不愧是你!Python 之父退休太无聊,进微软搞开源!
  3. vc采集网页内frame框架下所有元素(不指定具体table/form)
  4. python爬虫的应用-python网络爬虫应用实战
  5. convex function
  6. EJS学习(四)之语法规则下
  7. wxWidgets:wxCheckBox类用法
  8. 用正则表达式捕获标识符——随便说
  9. error: style attribute '@android:attr/windowEnterAnimation' not found
  10. iOS菜鸟之AFN的二次封装
  11. ESP32开发 2.添加.c.h并修改CMakeLists,来定制自己的工程
  12. [Python] L1-026. I Love GPLT-PAT团体程序设计天梯赛GPLT
  13. Python不能做游戏?游戏实战之-----《ink spill》(附游戏完整源码)
  14. 华为路由器支持ftp服务器,华为路由器FTP配置详解
  15. SpringCloud面试题及答案(2021年SpringCloud面试题大全带答案)
  16. ROS Launch使用总结
  17. 3-8 如何使用图片 CDN 优化图片
  18. 论文笔记-Understanding Convolution for Semantic Segmentation
  19. Day16:数据仓库设计
  20. Ajax提交与submit提交对比

热门文章

  1. 基于javaweb+jsp的设备维修管理系统(JavaWeb MySQL JSP Bootstrap Servlet SSM SpringBoot)
  2. Redisson文档
  3. Jsp中分页功能的实现
  4. 解决home end pgup pgdn没有独立,需要键盘映射的问题
  5. 基于MATLAB-GUI数字图像的水果边缘检测
  6. IT售前方法技能实战培训
  7. [摄影学习]-ZFC进阶操作学习
  8. python打开文件写入内容_python-11 文件的打开和写入
  9. 去除字符串中的重复字符,算法不使用额外缓冲。如abbc-abc
  10. 人员招聘与培训实务【2】