多线程编程基础
线程:进程上下文中执行的代码序列,又名轻量级进程。
在支持多线程的系统中,进程成为资源分配和保护的实体,线程是被调度执行的基本单元。进程是拥有资源的最小单位。
线程的分类
1)核心态线程(内核级线程):所有管理操作都是有操作系统内核完成的
2)用户态线程(用户级线程):一般我们操作的线程都是用户态线程。由用户级实现的线程 库来支持
用户级线程特征
1)用户级线程的创建和管理等操作无需内核参与,操作更快
2)并行性不高,一个线程被系统阻塞后,整个进程被阻塞
内核级线程特征
1)并行性高:多个线程可被提供是调度,充分利用多核处理器
2)创建和管理代价高
多线程(同一时刻可运行多个线程)优点
1)创建一个线程比创建一个进程的代价小
2)线程的切换比进程间的切换代价小
3)充分利用多核处理器
4)数据共享:使得线程之间的通信比进程间的通信更高效
5)快速响应特性:在系统繁忙的情况下,进程通过独立的线程及时响应用户的输入
Windows显示主要使用Win32 API实现
windows常用线程操作函数:创建线程函数、管理线程函数、终止线程函数、线程同步函数
线程必须从指定的函数开始,也就是这个函数其实就是线程的入口函数
DWORD WINAPI ThreadFunc(LPVOID IpvThreadParm);
线程创建函数是Windows API标准函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
HANDLE CreateThread( LPSECURITY_ATTRIBUTES IpThreadAttributes //安全属性,设为null就可以 SIZE_T dwStackSize, //内存的大小,栈的大小 可以为0 LPTHREAD_START_ROUTINE IpStartAddress, //函数的指针,指向线程函数 LPVOID IpParameter, //传递的参数,可以为空 DWORD dwCreationFlags, //创建标志,只能为0或者CREATE_SUSPENDED.0表示创建之后就会执行,CREATE_SUSPENDED表示创建之后处于挂起状态(观其计数器为1) LPDWORD IpThreadId //线程的ID好,可以不写 );//返回值是句柄
_beginthread函数是vc里面创建线程的函数。里面的实质还是API的创建函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
hThread=_beginthread( void(*strat_address)(void *),//线程函数的指针 unsigned stack_size, //栈的大小 void *arglist //参数列表 );
示例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<windows.h> #include<process.h> #include<iostream> #include<fstream> using namespace std; void ThreadFunc1(PVOID param){ while(1){ Sleep(1000); cout<<"This is ThreadFunc1"<<endl; } } void ThreadFunc2(PVOID param){ while(1){ Sleep(1000); cout<<"This is ThreadFunc2"<<endl; } } int main(){ int i=0; _beginthread(ThreadFunc1,0,NULL); _beginthread(ThreadFunc2,0,NULL); Sleep(3000); cout<<"end"<<endl; cin>>i;//这句话是为了让主程序停止在这里 return 0; }
线程是一个函数的表示方法
在时间片轮转中,主线程有优先权(主线程结束,子线程自动结束),跟编译器有关
main是主线程,另外两个是子线程,主线程走自己的,子线程也走自己的,三个线程同时执行
主线程死掉,子线程自动结束,三个线程是独立的。
这三个线程加上其余计算机上的线程一起在windows中进行调度,所以即便是先创建线程1,再创建线程2,但是也有可能先执行线程2再执行线程1.所以多次运行结果会不同
在分配给CPU区域的时候,该CPU可能将其挂起等等操作。队列也不同。最后结果可能就千差万别。需要使用更多的函数,使得线程满足我们自己的需求
进程中的每个线程都有挂起计数器。当挂起计数器为0时,线程被执行;当挂起计数器大于0时,调度器不去调取该线程
挂起线程函数 挂起计数器加1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
DWORD SuspendThread( HANDLE hThread;//线程函数的句柄 );
解挂函数 挂起计数器减1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
DWORD ResumeThread( HANDLE hThread //线程函数的句柄 );
线程终结函数
线程内部终结线程
VOID ExitThread(DWORD dwExitCode);//参数:退出码(线程以什么方式退出)
在线程外终结线程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
BOOL TerminateThread(//返回值bool表示执行成功还是失败 HANDLE hThread, //被终止的线程的函数名(句柄) DWORD dwExitCode //退出码 );
示例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<windows.h> #include<iostream> using namespace std; DWORD WINAPI FunOne(LPVOID param){ while(true){ Sleep(1000); cout<<"hello!"; } return 0; } DWORD WINAPI FunTwo(LPVOID param){ while(true){ Sleep(1000); cout<<"world!"; } return 0; } int main(){ int input=0; HANDLE hand1=CreateThread(NULL,0,FunOne,(void *)&input,CREATE_SUSPENDED,NULL); HANDLE hand2=CreateThread(NULL,0,FunTwo,(void *)&input,CREATE_SUSPENDED,NULL); while(true){ cin>>input; if(input==1){ ResumeThread(hand1); ResumeThread(hand2); } else { SuspendThread(hand1); SuspendThread(hand2); } } TerminateThread(hand1,1); TerminateThread(hand2,1); return 0; }
作者:孙建钊
出处:http://www.cnblogs.com/sunjianzhao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。