C++ 多线程(二)Win32多线程1
概述
Microsoft Windows 操作系统对多线程编程的支持几乎类似于 POSIX 线程提供的支持。区别不在于实际的功能,而在于 API 函数中的名称。
每个 Win32 进程至少有一个线程,我们将其称为主线程。我们将假设操作系统将以循环方式为每个程序线程提供一个时间片。事实上,Win32 程序中的线程将与其他程序中的线程和系统线程竞争 CPU,而这些其他线程可能有更高的优先级。
让我们看一下这个简单的例子。
主线程会生成一个新线程来增加 myThread 函数内的myCounter,同时主线程会一直等待用户输入一个字符(getchar()),并在我们输入除 ‘q’ 字符以外的任何时候打印出计数器值:
要使用 Windows 多线程函数,我们必须包含<windows.h>。为了创建线程,Windows API 提供了 CreateThread() 函数。
每个线程都有自己的堆栈。你可以使用 stackSize 参数指定新线程堆栈的大小(以字节为单位),这是下面例子中 CreateThread() 函数的第二个参数。如果这个整数值是零,那么线程将被赋予一个与创建线程相同大小的堆栈。
#include <windows.h>
#include <iostream>
DWORD WINAPI myThread(LPVOID lpParameter)
{
unsigned int& myCounter = *((unsigned int*)lpParameter);
while(myCounter < 0xFFFFFFFF) ++myCounter;
return 0;
}
int main(int argc, char* argv[])
{
using namespace std;
unsigned int myCounter = 0;
DWORD myThreadID;
HANDLE myHandle = CreateThread(0,
0,
myThread,
&myCounter,
0,
&myThreadID);
char myChar = ' ';
while (myChar != 'q')
{
cout << myCounter << endl;
myChar = getchar();
}
CloseHandle(myHandle);
return 0;
}
输出是:
0
868171493
1177338657
3782005161
4294967295
4294967295
...
每个执行线程都从创建过程中调用一个称为线程函数的函数开始。CreateThread() 函数的第三个参数 myThread 是线程函数。线程继续执行,直到线程函数返回。这个函数的地址(也就是线程的入口点)在 threadFunc 中指定。
通过输入字符 ‘q’,我们可以结束程序。
创建 Windows 的线程
最基本的 Windows 应用程序从一个线程开始。我们用来创建子线程的函数调用是 CreateThread()。下面的语法显示了传递给 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
);
参数
- lpThreadAttributes[输入参数, 可选]
一个指向 SECURITY_ATTRIBUTES 结构的指针,该结构决定返回的句柄是否可以被子进程继承。如果 lpThreadAttributes 为 NULL,则不能继承该句柄。
结构的 lpSecurityDescriptor 成员为新线程指定了一个安全描述符。如果 lpThreadAttributes 为 NULL,线程将获得默认的安全描述符。线程的默认安全描述符中的 ACL 来自创建者的主令牌。- dwStackSize[输入参数]
堆栈的初始大小,以字节为单位。系统将这个值舍入到最近的页面。如果此参数为零,则新线程将使用可执行文件的默认大小。- lpStartAddress[输入参数]
一个指针,指向要由线程执行的应用程序定义的函数。这个指针表示线程的起始地址。- lpParameter[输入参数