使用互斥对象:

#include <windows.h>
#include <iostream> #define THREADCOUNT 6 HANDLE ghMutex; DWORD WINAPI RunThreadFunction(LPVOID lpParam); int main(void)
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID; // 创建一个无所有者的互斥锁
ghMutex = CreateMutex(
NULL,
FALSE,
NULL); if (ghMutex == NULL)
{
std::cout << "CreateMutex error: " << GetLastError() << std::endl;
ExitProcess(2);
} for(int i = 0; i < THREADCOUNT; i++)
{
aThread[i] = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) RunThreadFunction,
NULL,
0,
&ThreadID); if( aThread[i] == nullptr )
{
std::cout << "CreateThread error: " << GetLastError() << std::endl;
ExitProcess(3);
}
} // 等到所有线程都终止
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE); for(int i = 0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]); // 关闭所有线程句柄并释放内存 CloseHandle(ghMutex); return 0;
} DWORD WINAPI RunThreadFunction(LPVOID lpParam)
{
UNREFERENCED_PARAMETER(lpParam); DWORD dwWaitResult; for(int i = 0; i < 5; i++)
{
// 获得互斥权
dwWaitResult = WaitForSingleObject(
ghMutex,
INFINITE); switch (dwWaitResult)
{
case WAIT_OBJECT_0:
try {
std::cout << i << " Thread " << GetCurrentThreadId() << " is run..."<< std::endl;
}
catch (...) {
if (! ReleaseMutex(ghMutex)) // 释放互斥权
{
std::cout << "ReleaseMutex error" << std::endl;
}
}
break;
// 线程处于不确定状态
case WAIT_ABANDONED:
return FALSE;
}
} return TRUE;
}

  代码运行结果:

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

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

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

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

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

#include <windows.h>
#include <tchar.h>
#include <strsafe.h> #define MAX_THREADS 3
#define BUF_SIZE 255 DWORD WINAPI MyThreadFunction( LPVOID lpParam );
void ErrorHandler(LPTSTR lpszFunction); typedef struct MyData {
int val1;
int val2;
} MYDATA, *PMYDATA; int _tmain()
{
PMYDATA pDataArray[MAX_THREADS];
DWORD dwThreadIdArray[MAX_THREADS];
HANDLE hThreadArray[MAX_THREADS]; for( int i=0; i<MAX_THREADS; i++ )
{
pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA)); if( pDataArray[i] == NULL )
{
ExitProcess(2);
} pDataArray[i]->val1 = i;
pDataArray[i]->val2 = i+100; hThreadArray[i] = CreateThread(
NULL,
0,
MyThreadFunction,
pDataArray[i],
0,
&dwThreadIdArray[i]); if (hThreadArray[i] == NULL)
{
ErrorHandler((LPTSTR)TEXT("CreateThread"));
ExitProcess(3);
}
} WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE); for(int i=0; i<MAX_THREADS; i++)
{
CloseHandle(hThreadArray[i]);
if(pDataArray[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, pDataArray[i]);
pDataArray[i] = NULL;
}
} return 0;
} DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
HANDLE hStdout;
PMYDATA pDataArray; TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars; hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdout == INVALID_HANDLE_VALUE )
return 1; pDataArray = (PMYDATA)lpParam; StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), pDataArray->val1, pDataArray->val2);
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL); return 0;
} void ErrorHandler(LPTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError(); FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL ); lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}

  

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. nested exception is org.apache.ibatis.binding.BindingException: Parameter 'cons_id' not found. Available parameters are [arg2, arg1, arg0, param3, param1, param2]

    修改DAO层的类中的方法,如下所示:

  2. PHP中PHP $_POST和PHP $_REQUEST及PHP $_GET的用法及区别

     笔者最近开始学习PHP语言大法,记录一下学习过程中遇到的知识点.          今天介绍的是php中有关 php $_post 和 php $_request 及 php $_get 的用法及区 ...

  3. shell中遍历数组的几种方式

    #!/bin/bash arr=( '你好') length=${#arr} echo "长度为:$length" # for 遍历 for item in ${arr[*]} d ...

  4. 【Struts 基础案例】

    LoginAction package k.action; import k.form.UserForm; import org.apache.struts.action.*; import java ...

  5. ubuntu16.04/ubuntu18.04安装网易云音乐

    一.下载1.0版本 下载地址:http://s1.music.126.net/download/pc/netease-cloud-music_1.0.0_amd64_ubuntu16.04.deb 下 ...

  6. 关于this和base的区别

    一句话总结:在有冲突得时候,base和this能够进行区分,在没有冲突得时候,是一样得. 基于成员调用 基于构造方法 参考: http://www.cnblogs.com/reommmm/archiv ...

  7. python实现基于百度路径规划接口的坐标对获取两点驾车距离的计算

    今天为大家介绍一种通过python实现坐标对间距离数据的获取方法.接口采用百度开发的路径规划接口. 1.调用接口: 接口:(传入起点坐标串,结束坐标串:ak值需要注册百度开发者) 接口详细说明 htt ...

  8. python练习:编写一个程序,要求用户输入一个整数,然后输出两个整数root和pwr,满足0<pwr<6,并且root**pwr等于用户输入的整数。如果不存在这样一对整数,则输入一条消息进行说明。

    python练习:编写一个程序,要求用户输入一个整数,然后输出两个整数root和pwr,满足0<pwr<6,并且root**pwr等于用户输入的整数.如果不存在这样一对整数,则输入一条消息 ...

  9. windows和ubuntu安装以太坊客户端Mist

    Mist钱包下载地址:https://github.com/ethereum/mist/releases Mist = Ethereum Wallet + Web3 浏览器 Dapp:bancor 史 ...

  10. Educational Codeforces Round 79 (Rated for Div. 2) - D. Santa's Bot(数论)

    题意:有$n$个孩子,第$i$个孩子有$k[i]$件想要的礼物,第$j$个礼物为$a[i][j]$,现在随机挑一个孩子,从他想要的礼物里面随机挑一个,然后送给另一个孩子$($这个孩子可以和第一个孩子是 ...