C++多线程1.createthread
C++ 多线程知识1.多线程入门 CreateThread 20131021
1.介绍WinAPI中的CreateThread
函数原型:
HANDLE WINAPI CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_STACK_ROUTLINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
参数介绍:
第一个参数是指向SECURITY_ATTRIBUTES struct 类型的指针,一般设置成为NULL,在Windows 98系统中会忽略该参数。
第二个参数是用于新线程的初始化堆栈大小,默认值是0,也就是在任何情况下,Windows会根据需要动态的延长堆栈的大小。
第三个参数是指向线程运行函数的指标,函数名称没有限制,但是必须是以下形式声明的:
DWORD WINAPI ThreadProc(PVOID pPrama); 返回值是一个DWORD 4字节的数据,参数是一个PVOID的指针,也就是void类型的指针,函数中根据需要,利用指针获取参数。
第四个参数就是传递给线程函数参数的指针,类型是LPVOID;
第五个参数通常设置成为0,表示创建完成线程之后,立即执行该线程,当简历线程不马上执行的话,可以使用CREATE_SUSPENED,线程将暂停,知道呼叫ResumeThread()函数类恢复线程。
第六个参数是一个指标,指向接受执行ID值的变量;
2.WINAPI CreateThread的操作系统层面分析
当使用CreateProcess WINAPI调用的时候,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础之上创建一个新的线程,操作系统的底层实现原理如下:
在内核对象上分配一个线程标识/句柄(也就是一个指针),有CreateThread函数返回;
把线程退出码设置成为STILL_ACTIVE, 把线程挂起的数目++(也就是这个线程处于SUSPENED状态);
给线程分配context结构,也就是线程上下文;
分配两页的物理存储已准备栈,保护页设置成为PAGE_READWRITE,第二页设置成为PAGE_GUARD;
lpStartAddress和lpvThread值放在栈顶,使他们成为传送给StartOfThread的参数;
把Context线程上下文的栈指针指向栈顶,指令指向startOfThread函数。
3.CreateThread的例子
3.1简单的创建线程启动
DWORD /*WINAPI*/ ThreadProc(LPVOID lpdwThreadParam){
for (int i = 0; i < 10; i++){
cout << "Thread fun display " << i << endl;
Sleep(1000);
}
return 0;
}
int main(){
HANDLE hThread = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) &ThreadProc, NULL, 0, NULL);
CloseHandle(hThread);
for (int i = 0; i < 10; i++){
cout << "main thread run " <<i << endl;
Sleep(1000);
}
cout << endl;
return 0;
}
需要注意的地方:
在传递函数指针的时候,如果我们的ThreadProc没有声明是WINAPI格式,那么在传递函数指针的时候,需要将它转换成为(LPTHREAD_START_ROUTINE)&ThreadProc,但是如果线程处理函数声明形式为WINAPI的话,就可以直接传递函数名称。
3.2线程之间同步的问题
这种情况下,会出现输出不换行,或者是换两行的问题。但是初步的 多线程已经具备。多线程并发的运行使用一些资源的话,我们不能够保证这些资源都能够被正确的利用,因为整个时候资源并不是独占的。输出到屏幕就会占用资源,但main线程没有输出endl换行的时候,就让给另一个线程,就会出现各种悲剧的场景;
解决上面的问题,就需要使用同步机制,对于一个资源被多个线程共用,会造成程序的错误,一个线程拥有对贡献资源的独占,就可以解决上面的问题了:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,//SD
BOOL bInitialOwner,// initial owner
LPCTSTR lpName // object name
)
干函数用于创造一个独占资源,第一个参数我们没有使用设置成为NULL,第二个参数是他的进程,第三个参数是指定资源的名称
HANDLE hMutex = CreateMutex(NULL,TRUE, “screen”);
这一条语句创建可一个名称是screen的并且归属创建它的进程的资源
对应占有资源就有释放资源,一旦进程释放资源,该资源就不属于他了,
BOOL ReleaseMutex(HANDLE hMutex);
释放资源之后如果再想申请资源也是可以的
DWORD WaitForSingleObject(
HANDLE hHandle,// handle to object
DWORD dwMilliseconds // time-out interval);
第一个参数是申请资源的句柄,第二个参数一般指为INFINITE,表示一直等待资源,如果指定0的话,就是一旦得不到资源就立刻返回,也可以指定在一定的时间内返回。
源代码例子:
#include <iostream>
#include <Windows.h>
using namespace std;
HANDLE hMutex;
DWORD WINAPI Fun(LPVOID lpParamter){
for (int i = 0; i < 10; i++){
WaitForSingleObject(hMutex, INFINITE);
cout<< "Fun display" << i << endl;
ReleaseMutex(hMutex);
Sleep(1000);
}
return 0;
}
int main(){
HANDLE hThread = CreateThread(NULL, 0,Fun,NULL, 0, NULL);
hMutex = CreateMutex(NULL, FALSE, "screen");
for (int i = 0; i < 10; i++){
WaitForSingleObject(hMutex, INFINITE);
cout << "main thread run " <<i << endl;
Sleep(1000);
ReleaseMutex(hMutex);
}
cout << endl;
CloseHandle(hThread);
CloseHandle(hMutex);
return 0;
}
3.3关于线程等待的问题
当主线程结束的时候,分支线程还没有结束的话,进程会直接退出,分支线程也会结束,所以在程序中有可能会出现分支线程还没有运行完成,但是主线程已经结束,那么分线程也不会继续运行下去,直接被卡掉。所以这个时候我们需要做一些处理。
同时注意一个函数 CloseHandle(HANDLE)函数式用于关闭HANDLE的。
主线程中每创建一个线程的话,会返回一个线程的句柄HANDLE,事后,我们就可以对线程执行某些操作,比如查询线程的状态等考的就是线程的句柄。如果没有句柄的话,系统就不会知道如何得到线程的状态。但是保持这个线程的句柄不是线程运行的条件。
关闭线程句柄知识释放句柄资源,新开启的线程之后,如果不在利用该线程的句柄,我们就应该释放掉线程的句柄,释放系统的资源。关闭线程句柄和线程的结束与否没有关系。系统中的句柄资源是有限的。
对于CloseHandle函数只是减少一个对于hThread的引用计数,用于释放线程的资源,但不是用于终止线程的。终止线程使用的是terminalthread or exitthread。 TerminateThread的使用会导致各类资源的释放问题,主要是和该线程相连的各种DLL,他们都无法得到线程退出的通知。应该在线程中自然的退出(ExitThread)或是直接调用ExitThread线程,退出的时候应该有同步对象和其他机制实现,主线程一般使用的是WaitForSingleObject函数等待该线程的句柄,以确保现成的退出。
例子:
HANDLE hMutex;
DWORD WINAPI Fun(LPVOID lpParamter){
for (int i = 0; i < 10; i++){
WaitForSingleObject(hMutex, INFINITE);
cout << "Fun display" << i << endl;
ReleaseMutex(hMutex);
Sleep(1000);
}
return 0;
}
int main(){
HANDLE hThread = CreateThread(NULL, 0,Fun,NULL, 0, NULL);
hMutex = CreateMutex(NULL, FALSE, "screen");
for (int i = 0; i < 10; i++){
WaitForSingleObject(hMutex, INFINITE);
cout << "main thread run " <<i << endl;
//Sleep(1000);
ReleaseMutex(hMutex);
}
cout << endl;
WaitForSingleObject(hThread, INFINITE);//等待分线程的退出机制
CloseHandle(hThread);
CloseHandle(hMutex);
return 0;
}
追梦的飞飞
于广州中山大学 201310221
HomePage: http://yangtengfei.duapp.com
C++多线程1.createthread的更多相关文章
- 多线程编程 CreateThread(解释了TContext)
function CreateThread( lpThreadAttributes: Pointer; {安全设置} dwStackSize: DWORD; ...
- delphi之多线程编程
本文的内容取自网络,并重新加以整理,在此留存仅仅是方便自己学习和查阅.所有代码均亲自测试 delphi7下测试有效.图片均为自己制作. 多线程应该是编程工作者的基础技能, 但这个基础我从来没学过,所以 ...
- C++的CreateThread实例
function CreateThread( lpThreadAttributes: Pointer; {安全设置} dwStackSize: DWORD; ...
- [转]Delphi多线程编程入门(一)
最近Ken在比较系统地学习Delphi多线程编程方面的知识,在网络上查阅了很多资料.现在Ken将对这些资料进行整理和修改,以便收藏和分享.内容基本上是复制粘贴,拼拼凑凑,再加上一些修改而来.各个素材的 ...
- delphi 中几种多线程操作方式
在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:http: ...
- 总结windows多线程同步互斥
windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...
- DELPHI中多线程知识【转】
本文的内容取自网络,并重新加以整理,在此留存仅仅是方便自己学习和查阅.所有代码均亲自测试 delphi7下测试有效.图片均为自己制作. 多线程应该是编程工作者的基础技能, 但这个基础我从来没学过,所以 ...
- windows多线程同步互斥--总结
我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...
- WINDOWS-API:关于线程CreateThread,_beginthead(_beginthreadex),AfxBeginThread
[转]windows多线程编程CreateThread,_beginthead(_beginthreadex)和AfxBeginThread的区别 在Windows的多线程编程中,创建线程的函数主要有 ...
随机推荐
- js的同步异步
由于js没有多线程,所以处理多任务的时候,可以用异步回调来解决.js中setTimeout.setInterval.ajax(jq中可以选择同步或异步)均会开启异步.遇到异步模块,会将其推入值任务队列 ...
- 714. Best Time to Buy and Sell Stock with Transaction Fee
问题 给定一个数组,第i个元素表示第i天股票的价格,可执行多次"买一次卖一次",每次执行完(卖出后)需要小费,求最大利润 Input: prices = [1, 3, 2, 8, ...
- 机器学习与R语言:kNN
#---------------------------------------- # 功能描述:演示kNN建模过程 # 数据集:威斯康星乳腺癌诊断 # #---------------------- ...
- lvds split两channel输出到一个屏显示
转:https://blog.csdn.net/changqing1990/article/details/81128552 其实之前写过LCD/LVDS的一些时序的基本概念<与LCD移植相关的 ...
- Kafka学习之(四)PHP操作Kafka
简单测试 环境:Centos6.4,PHP7,kafka服务器IP:192.168.9.154,PHP服务器:192.168.9.157 在192.168.9.157创建目录和文件. //生产者 &l ...
- [pixhawk笔记]6-uORB流程及关键函数解析
本文中将结合代码.文档及注释,给出uORB执行流程及关键函数的解析,由于uORB的机制实现较为复杂,所以本文主要学习如何使用uORB的接口来实现通信.回到上一篇笔记中的代码: #include < ...
- 安卓Android第三方登录-QQ登录
要实现QQ第三方登录,其实只需要一个封装类:QQLoginManager 几乎 三行代码 就实现QQ登录功能 这里先给出Github开源项目地址,项目下有详细的使用说明 下面就开始详细说一说怎么实 ...
- Spring Tomcat启动过程
入口,配置再web.xml中, 初始化applicationContext 创建webApplicationContext,这里可加载web.xml文件中定义了contextClass 获取conte ...
- 20145321 《Java程序设计》第4周学习总结
20145321 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承与多态 6.1 何谓继承 1.继承共同行为: 继承基本上就是避免多个类间重复定义的行为. Pull Up ...
- 20145328 《Java程序设计》实验二实验报告
20145328 <Java程序设计>实验二实验报告 实验名称 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 ...