线程创建函数介绍
创建线程可以使用系统提供的API函数:CreateThread来完成,该函数将创建一个线程,其函数声明如下:
HANDLE WINAPI CreateThread( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in SIZE_T dwStackSize, __in LPTHREAD_START_ROUTINE lpStartAddress, __in_opt LPVOID lpParameter, __in DWORD dwCreationFlags, __out_opt LPDWORD lpThreadId );下面简单介绍CreateThread函数的每个参数:
lpThreadAttributes
执向LPSECURITY_ATTRIBUTES结构体的指针,使用时我们一般设置为NULL,表示让该线程使用默认的安全性;
dwStackSize
设置线程初始栈的大小,即线程可以将多大的地址空间用于它自己的栈,以字节为单位。默认设置为0,表示使用与调用该函数的线程相同的栈空间大小;
lpStartAddress
指向应用程序定义的LPTHREAD_START_ROUTINE类型的函数的指针,表明新线程的起始地址,由新线程执行;这个函数的声明必须是如下形式,函数名字不做要求:
DWORD WINAPI ThreadProc(LPVOID lpParameter);
lpParameter
新线程的入参,是LPVOID类型,必要时进行相应类型的强制转换;
dwCreationFlags
设置用于控件线程创建的附加标记,若为0表示线程创建后就立即执行,若为CREATE_SUSPENDED表示创建后处于暂停状态;
lpThreadId
这个是个返回值,指向一个变量,用来接收线程的ID,当线程创建成功后,系统就会分配一个线程ID;如果我们不关心线程ID,我们可以设置为NULL;
实例1
新建一个Win32 Console Application类型的工程,并命名为MultiThread.cpp;
代码如下:
// MultiThread.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <iostream> using namespace std; //新线程的起始地址 DWORD WINAPI Thread1Proc(LPVOID lpParameter) { cout << "Thread1 is ruuning" << endl; return 0; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hThread1 = NULL; //创建新的线程 hThread1 = CreateThread(NULL,0,Thread1Proc,NULL,0,NULL); //无须对新线程设置优先级等操作,关闭之 //良好的编码习惯 CloseHandle(hThread1); cout << "main thread is running" << endl; return 0; }我们执行(Ctrl + F5)这段代码多次后,可以发现其结果有三种情况,导致这情况出现的主要原因是:
操作系统为每一个运行的线程安排一个的CPUT时间---时间片。系统通过一种循环方式为线程提供时间片,线程仅在自己的时间内运行,因为时间片非常的短,所以给我们的感觉就像多个线程是同时运行的,每次执行时系统分配的时间片都是不一致的,所以有时候能执到线程1,有时候在主线程的时间片内,主线程已经执行完毕,主线程退出,线程1没有机会执行;
情况1
情况2
情况3
在我们的main函数返回之前,添加一个Sleep(1000)语句,就能确保执行结果和预期一致,即情况3;
解释如下:
Sleep(1000)表示让主线程睡眠1秒,Sleep的入参是毫秒为单位;由于主线程进入睡眠状态,主线程放弃了执行的权利,线程1得到了运行权利,线程1在1秒内足以执行完成,线程1结束;在1秒后,主线程睡醒,主线程执行完毕,程序退出;
实例2
在这个实例中我们引入一个全局的计数器g_Index,在两个线程中分别打印这个index 和执行的线程标识,其代码如下:
int g_nIndex = 0; const int nMaxCnt = 100; //新线程的起始地址 DWORD WINAPI Thread1Proc(LPVOID lpParameter) { while (g_nIndex++ < nMaxCnt) { cout <<"Index = "<< g_nIndex << " "; cout << "Thread1 is ruuning" << endl; } return 0; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hThread1 = NULL; //创建新的线程 hThread1 = CreateThread(NULL,0,Thread1Proc,NULL,0,NULL); //无须对新线程设置优先级等操作,关闭之 //良好的编码习惯 CloseHandle(hThread1); while (g_nIndex++ < nMaxCnt) { cout << "Index = " << g_nIndex << " "; cout << "main thread is running" << endl; } return 0; }运行结果:
我们发现某些行的打印和我们的预期有些不符,例如:“Index = 3Index = 2 main thread is running”,这个就是多线程执行带来的问题,可以使用互斥量来解决,这暂不讨论;
同时我们也可以发现主线程和线程1是交替执行的,这里也体现的了多线程的执行是按照时间片来运行的;