使用互斥对象:

  1. #include <windows.h>
  2. #include <iostream>
  3.  
  4. #define THREADCOUNT 6
  5.  
  6. HANDLE ghMutex;
  7.  
  8. DWORD WINAPI RunThreadFunction(LPVOID lpParam);
  9.  
  10. int main(void)
  11. {
  12. HANDLE aThread[THREADCOUNT];
  13. DWORD ThreadID;
  14.  
  15. // 创建一个无所有者的互斥锁
  16. ghMutex = CreateMutex(
  17. NULL,
  18. FALSE,
  19. NULL);
  20.  
  21. if (ghMutex == NULL)
  22. {
  23. std::cout << "CreateMutex error: " << GetLastError() << std::endl;
  24. ExitProcess(2);
  25. }
  26.  
  27. for(int i = 0; i < THREADCOUNT; i++)
  28. {
  29. aThread[i] = CreateThread(
  30. NULL,
  31. 0,
  32. (LPTHREAD_START_ROUTINE) RunThreadFunction,
  33. NULL,
  34. 0,
  35. &ThreadID);
  36.  
  37. if( aThread[i] == nullptr )
  38. {
  39. std::cout << "CreateThread error: " << GetLastError() << std::endl;
  40. ExitProcess(3);
  41. }
  42. }
  43.  
  44. // 等到所有线程都终止
  45. WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
  46.  
  47. for(int i = 0; i < THREADCOUNT; i++ )
  48. CloseHandle(aThread[i]); // 关闭所有线程句柄并释放内存
  49.  
  50. CloseHandle(ghMutex);
  51.  
  52. return 0;
  53. }
  54.  
  55. DWORD WINAPI RunThreadFunction(LPVOID lpParam)
  56. {
  57. UNREFERENCED_PARAMETER(lpParam);
  58.  
  59. DWORD dwWaitResult;
  60.  
  61. for(int i = 0; i < 5; i++)
  62. {
  63. // 获得互斥权
  64. dwWaitResult = WaitForSingleObject(
  65. ghMutex,
  66. INFINITE);
  67.  
  68. switch (dwWaitResult)
  69. {
  70. case WAIT_OBJECT_0:
  71. try {
  72. std::cout << i << " Thread " << GetCurrentThreadId() << " is run..."<< std::endl;
  73. }
  74. catch (...) {
  75. if (! ReleaseMutex(ghMutex)) // 释放互斥权
  76. {
  77. std::cout << "ReleaseMutex error" << std::endl;
  78. }
  79. }
  80. break;
  81. // 线程处于不确定状态
  82. case WAIT_ABANDONED:
  83. return FALSE;
  84. }
  85. }
  86.  
  87. return TRUE;
  88. }

  代码运行结果:

  这里会发现线程ID都是同一个...这是因为,这段代码中,在try语句块忘记释放锁了,所以最初执行的线程执行完`RunThreadFunction`函数中的循环后都没有释放掉,所以出现了这种情况。

  如果直接去掉互斥锁会看到输出十分混乱...原因也在于std::cout的输出是拼接的。如果用printf来输出会好一些,但输出的 i 可能会是混乱的,如下图:

  因为C++中没有finally关键字,final好像也不是用来做异常处理的,在try中也加上锁后的运行效果:

  可以看出执行顺序为:因为线程数定义为6个,所以就创建6个线程来同时执行一个函数,函数中的5次循环会使得阻塞,但代码中加了互斥锁,为了保持同步,所以其他线程会等待当前这个进程中所有线程执行完...

  下面是在MSDN看到的一个创建线程的例子,如果想要传递其他类型的参数且没有类型转换的警告,可以这样做(用到了结构体):

  1. #include <windows.h>
  2. #include <tchar.h>
  3. #include <strsafe.h>
  4.  
  5. #define MAX_THREADS 3
  6. #define BUF_SIZE 255
  7.  
  8. DWORD WINAPI MyThreadFunction( LPVOID lpParam );
  9. void ErrorHandler(LPTSTR lpszFunction);
  10.  
  11. typedef struct MyData {
  12. int val1;
  13. int val2;
  14. } MYDATA, *PMYDATA;
  15.  
  16. int _tmain()
  17. {
  18. PMYDATA pDataArray[MAX_THREADS];
  19. DWORD dwThreadIdArray[MAX_THREADS];
  20. HANDLE hThreadArray[MAX_THREADS];
  21.  
  22. for( int i=0; i<MAX_THREADS; i++ )
  23. {
  24. pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));
  25.  
  26. if( pDataArray[i] == NULL )
  27. {
  28. ExitProcess(2);
  29. }
  30.  
  31. pDataArray[i]->val1 = i;
  32. pDataArray[i]->val2 = i+100;
  33.  
  34. hThreadArray[i] = CreateThread(
  35. NULL,
  36. 0,
  37. MyThreadFunction,
  38. pDataArray[i],
  39. 0,
  40. &dwThreadIdArray[i]);
  41.  
  42. if (hThreadArray[i] == NULL)
  43. {
  44. ErrorHandler((LPTSTR)TEXT("CreateThread"));
  45. ExitProcess(3);
  46. }
  47. }
  48.  
  49. WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
  50.  
  51. for(int i=0; i<MAX_THREADS; i++)
  52. {
  53. CloseHandle(hThreadArray[i]);
  54. if(pDataArray[i] != NULL)
  55. {
  56. HeapFree(GetProcessHeap(), 0, pDataArray[i]);
  57. pDataArray[i] = NULL;
  58. }
  59. }
  60.  
  61. return 0;
  62. }
  63.  
  64. DWORD WINAPI MyThreadFunction( LPVOID lpParam )
  65. {
  66. HANDLE hStdout;
  67. PMYDATA pDataArray;
  68.  
  69. TCHAR msgBuf[BUF_SIZE];
  70. size_t cchStringSize;
  71. DWORD dwChars;
  72.  
  73. hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  74. if( hStdout == INVALID_HANDLE_VALUE )
  75. return 1;
  76.  
  77. pDataArray = (PMYDATA)lpParam;
  78.  
  79. StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), pDataArray->val1, pDataArray->val2);
  80. StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
  81. WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
  82.  
  83. return 0;
  84. }
  85.  
  86. void ErrorHandler(LPTSTR lpszFunction)
  87. {
  88. LPVOID lpMsgBuf;
  89. LPVOID lpDisplayBuf;
  90. DWORD dw = GetLastError();
  91.  
  92. FormatMessage(
  93. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  94. FORMAT_MESSAGE_FROM_SYSTEM |
  95. FORMAT_MESSAGE_IGNORE_INSERTS,
  96. NULL,
  97. dw,
  98. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  99. (LPTSTR) &lpMsgBuf,
  100. 0, NULL );
  101.  
  102. lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
  103. StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
  104. MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
  105.  
  106. LocalFree(lpMsgBuf);
  107. LocalFree(lpDisplayBuf);
  108. }

  

C/C++ — CreateThread 相关 API的更多相关文章

  1. OpenGL FrameBufferCopy相关Api比较(glCopyPixels,glReadPixels,glCopyTexImage2D,glFramebufferTexture2D)

    OpenGL FrameBufferCopy相关Api比较 glCopyPixels,glReadPixels,glCopyTexImage2D,glFramebufferTexture2D 标题所述 ...

  2. QQ音乐的各种相关API

    QQ音乐的各种相关API 分类: oc2014-01-29 15:34 2676人阅读 评论(2) 收藏 举报 基本上论坛里做在线音乐的都在用百度的API,进来发现百度的API不仅歌曲的质量不可以保证 ...

  3. addChildViewController相关api深入剖析

    注:本文根据个人的实践和理解写成,若有不当之处欢迎斧正和探讨! addChildViewController是一个从iOS5开始支持的api接口,相关的一系列的接口是用来处理viewcontrolle ...

  4. [原创]java WEB学习笔记44:Filter 简介,模型,创建,工作原理,相关API,过滤器的部署及映射的方式,Demo

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  5. 关于iOS中用AudioFile相关API解码或播放AAC_HE_V2时仅仅能识别单声首22.05k採样率的问题

    关于iOS中用AudioFile相关API解码或播放AAC_HE_V2时仅仅能识别单声首22.05k採样率的问题 在官方AQPlayer Demo 和 aqofflinerender中.都用了Audi ...

  6. TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现

    题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com linu ...

  7. 【Socket编程】Java中网络相关API的应用

    Java中网络相关API的应用 一.InetAddress类 InetAddress类用于标识网络上的硬件资源,表示互联网协议(IP)地址. InetAddress类没有构造方法,所以不能直接new出 ...

  8. java 11 移除的一些其他内容,更简化的编译运行程序,Unicode 10,移除了不太使用的JavaEE模块和CORBA技术,废除Nashorn javascript引擎,不建议使用Pack200 相关api

    移除的一些其他内容 移除项 移除了com.sun.awt.AWTUtilities 移除了sun.misc.Unsafe.defineClass, 使用java.lang.invoke.MethodH ...

  9. python 以单例模式封装logging相关api实现日志打印类

    python 以单例模式封装logging相关api实现日志打印类   by:授客QQ:1033553122 测试环境: Python版本:Python 2.7   实现功能: 支持自由配置,如下lo ...

随机推荐

  1. 阿里云云服务器ECS开发者工具包(SDK)

    阿里云云服务器ECS开发者工具包(SDK) 前提条件 使用Alibaba Cloud SDK for Java,您需要一个阿里云账号和访问密钥(AccessKey). 请在阿里云控制台中的Access ...

  2. python自动更新升级失败解决方案

    1,使用python -m pip install --upgrade pip升级失败 2,使用python -m pip install -U --force-reinstall pip依然失败 3 ...

  3. 激活4500-X RTU license

    1.查看设备license Switch#sho version Cisco IOS Software, IOS-XE Software, Catalyst 4500 L3 Switch Softwa ...

  4. javaweb项目运转流程

    做web项目,不仅要会做,还需要了解其工作流程,为什么这么做!这些知道了.其他的都是渣渣.上图!对于web 项目了解他的运行流程之后,基本其他的都不是问题.web项目还是很简单的 这是简化的开发时常用 ...

  5. 安装pyhanlp

    安装pyhanlp pyhanlp是java写的,外层封装了python. 对于新手,在使用的时候稍有难度. 1. 下载源码 https://github.com/hankcs/pyhanlp git ...

  6. 第一阶段集训(这篇先写写tarjan以及圆方树)

    第一阶段的集训结束了w,不得不说oi太长时间不整是会退步的. 怎么说好呢,集训这几天过的很充实,知识收货很多,题调的也不少,自己的目标更明确了吧,不过这几天集训也是可以看出蒟蒻就是蒟蒻,还是太菜了.. ...

  7. Vue-设置默认路由选中

    需求分析: 一个导航组件,需要其中一个是选中状态,并且样式呈现高亮,选中的导航对应的页面也需要展示出来. 功能实现: router-link内置有一个选中状态,当处于当前路由时,会给 router-l ...

  8. laravel 语言包拓展

    laravel 使用make:auth生成用户认证,登录表单是英文版本的,打开模板文件(resources/views/auth/login.blade.php),此模板文件是我们刚刚使用 make: ...

  9. kubernetes的Ingress资源介绍

    Ingress 的资源帮助信息介绍 [root@master ~]# kubectl explain ingress KIND: Ingress VERSION: extensions/v1beta1 ...

  10. "%Error opening tftp://255.255.255.255/network config"

    问题:服务配置错误消息(Service Configuration Error Messages) 有时,在通过Cisco IOS软件启动Cisco设备期间,会显示与这些类似的错误消息: %Error ...