多线程程序设计之创建线程(Windows)

一、线程概述

理解Windows内核对象

线程是系统内核对象之一。在学习线程之前,应先了解一下内核对象。内核对象是系统内核分配的一个内存块,该内存块描述的是一个数据结构,其成员负责维护对象的各种信息。内核对象的数据只能由系统内核来访问,应用程序无法在内存中找到这些数据结构并直接改变他们的内容。

常用的系统内核对象有事件对象、文件对象、作业对象、互斥对象、管道对象、进程对象和线程对象等。不同类型的内核对象,其数据结构各有不同。

理解进程和线程

进程被认为是一个正在运行的程序的实例,它也属于系统内核对象。可以将进程简单的理解为一个容器,它只是提供空间,执行程序的代码是由线程来实现的。线程存在于进程中,它负责执行进程地址空间中的代码。当一个进程创建时,系统会自动为其创建一个线程,该线程被称为主线程。在主线程中用户可以通过代码创建其他线程,当进程中的主线程结束时,进程也就结束了。

二、线程的创建

Windows下,创建线程有多种方式,以下将逐一介绍。注意它们的区别。

使用CreateThread函数创建线程

Windows API函数。该函数在主线程的基础上创建一个新线程。微软在Windows API中提供了建立新的线程的函数CreateThread。

HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,//线程安全属性
DWORD dwStackSize,//堆栈大小
LPTHREAD_START_ROUTINE lpStartAddress,//线程函数
LPVOID lpParameter,//线程参数
DWORD dwCreationFlags,//线程创建属性
LPDWORD lpThreadId//线程ID
);

代码示例如下:

#include "stdafx.h"
#include
#include
using namespace std;

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
	cout << "thread function Fun1Proc!\n";

	return 0;
}

int main()
{
	HANDLE hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
	CloseHandle(hThread1);

	Sleep(1000);
	cout << "main end!\n";
	system("pause");
    return 0;
}

运行结果:
多线程程序设计之创建线程(Windows)_第1张图片

使用_beginthreadex函数创建线程

除了使用CreateThread API函数创建线程外,还可以用C++语言提供的_beginthreadex函数来创建线程。

uintptr_t _beginthreadex( // NATIVE CODE  
   void *security,  //线程安全属性
   unsigned stack_size,  //线程的栈大小
   unsigned ( *start_address )( void * ),//线程函数  
   void *arglist,  //传递到线程函数中的参数
   unsigned initflag,  //线程初始化标记
   unsigned *thrdaddr   //线程ID
); 

代码示例:

#include "stdafx.h"
#include
#include
#include
using namespace std;

unsigned int _stdcall ThreadProc(LPVOID lpParameter)
{
	cout << "thread function ThreadProc!\n";
	return 0;
}

int main()
{
	_beginthreadex(NULL, 0, ThreadProc, 0, 0, NULL);

	Sleep(1000);
	cout << "main end!\n";
	system("pause");
    return 0;
}

使用AfxBeginThread函数创建线程

在MFC应用程序中,还可以使用AfxBeginThread函数创建一个线程。MFC提供了两个重载版的AfxBeginThread,一个用于用户界面线程,另一个用于工作者线程。这里只讲工作者线程。

CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,
  LPVOID lParam,
  int nPriority = THREAD_PRIORITY_NORMAL,
  UINT nStackSize = 0,
  DWORD dwCreateFlags = 0,
  LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
  );//用于创建工作者线程

返回值: 成功时返回一个指向新线程的线程对象的指针,否则NULL。
pfnThreadProc : 线程的入口函数,声明一定要如下: UINT MyThreadFunction(LPVOID pParam),不能设置为NULL;
pParam : 传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.
nPriority : 线程的优先级,一般设置为 0 .让它和主线程具有共同的优先级.
nStackSize : 指定新创建的线程的栈的大小.如果为 0,新创建的线程具有和主线程一样的大小的栈
dwCreateFlags : 指定创建线程以后,线程有怎么样的标志.可以指定两个值:

  • CREATE_SUSPENDED : 线程创建以后,会处于挂起状态,直到调用ResumeThread
  • 0 : 创建线程后就开始运行。

lpSecurityAttrs : 指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性。如果为 NULL,那么新创建的线程就具有和主线程一样的安全性。

代码略。

其他方式

创建线程还可以用boost线程库创建,也可以用c++11新标准中的线程库(std::thread)创建线程。建议采用c++11中的线程库创建线程,极为方便。且跨平台,是语言层面的。后面会学习到c++11线程库的使用。

最后,搜索并关注微信公众号:让我思考一下。获得最新技术分享!

你可能感兴趣的:(C++)