在window环境下,Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作:
1. 主要的函数列表
序号 |
函数名 |
功能 |
1 |
CreateThread() |
创建一个新线程 |
2 |
ExitThread() |
正常结束一个线程的执行 |
3 |
TerminateThead() |
强制终止一个线程的执行 |
4 |
ResumeThread() |
重启一个线程 |
5 |
SuspendThread() |
挂起一个线程 |
6 |
GetExiCodeThread() |
得到一个线程的退出码 |
7 |
GetThreadPriority() |
得到一个线程的优先级 |
8 |
SetThreadPriority() |
设置一个线程的优先级 |
9 |
CloseHandle() |
关闭一个线程的句柄 |
10 |
CreateRemoteThread() |
再另一个进程中创建一个新线程 |
11 |
PostThreadMessage() |
发送一条消息给指定的线程 |
12 |
GetCurrentThread() |
得到当前的线程句柄 |
13 |
GetCurrentThreadId() |
得到当前线程的ID |
14 |
GetThreadId() |
得到指定线程的ID |
15 |
WaitForSingleObject() |
等待单个对象 |
16 |
WaitForMultipleObjects() |
等待多个对象 |
关于多线程的API函数还有很多,以上只是列出了一些比较常用的函数,欲知更多函数和函数的使用方法,请参考MSDN或网络资源,在此就不再介绍了。
CreateThread函数原型:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 不重要,一般设置为NULL
SIZE_T dwStackSize, // 堆栈大小,不重要,一般设置为0,表示使用默认堆栈大小
LPTHREAD_START_ROUTINE lpStartAddress, // 函数指针,传入函数名或指针即可
__drv_aliasesMem LPVOID lpParameter, // 参数指针,供函数使用
DWORD dwCreationFlags, // 不重要,一般设置为0
LPDWORD lpThreadId // 指针,用于保存线程的id,一般设置为NULL
);
参数说明:
lpThreadAttributes:指向SECURITY_ATTRIBUTES 结构的指针,该结构确定子进程是否可以继承返回的句柄。如果 lpThreadAttributes为NULL,则无法继承句柄。
dwStackSize:堆栈的初始大小,以字节为单位。系统将此值四舍五入到最近的页面。如果此参数为0,则新线程使用可执行文件的默认大小,1M。
lpStartAddress:指向由线程执行的应用程序定义函数的指针。该指针表示线程的起始地址。
lpParameter:指向要传递给线程的变量的指针。
dwCreationFlags:控制线程创建的标志。详细看下图。
lpThreadId:指向接收线程标识符的变量的指针。如果此参数为 NULL,则不返回线程标识符。
返回值:
如果函数成功,则返回值是新线程的句柄。
如果函数失败,则返回值为NULL。
2. 创建线程
在 Windows API 中,一般使用 CreateThread()
函数创建线程。
创建一个不带参数的线程
#include<iostream>
#include<windows.h>
using namespace std;
// 编写了一个我的线程函数
DWORD WINAPI MyThread(LPVOID lpParamter)
{
cout << "fuck the multithread !\n";
return 0L;
}
int main ()
{
// 创造线程
CreateThread(NULL, 0, MyThread, NULL, 0, NULL);
// 记得等待线程结束
system("PAUSE");
return 0;
}
创建一个带参线程:lpParam参数
下面是使用Windows API创建线程并打印数字并获取重要的线程信息的代码示例:
#include <iostream>
#include <Windows.h>
DWORD WINAPI ThreadFunction(LPVOID lpParam)
{
// 获取当前线程ID
DWORD threadId = GetCurrentThreadId();
std::cout << "Thread ID: " << threadId << std::endl;
// 获取线程传入的参数
int threadParam = *(int*)lpParam;
for (int i = 0; i < threadParam; i++)
{
std::cout << i << std::endl;
}
return 0;
}
int main()
{
int num = 10;
// 创建线程
HANDLE hThread = CreateThread(NULL, 0, ThreadFunction, &num, 0, NULL);
if (hThread == NULL)
{
cout << "Failed to create thread" << endl;
return 1;
}
// 等待线程结束
WaitForSingleObject(hThread, INFINITE);
// 关闭线程句柄
CloseHandle(hThread);
return 0;
}
3. 线程通信
以下是通过共享变量实现线程间通信的代码示例:
#include <Windows.h>
#include <iostream>
DWORD WINAPI ThreadFunction1(LPVOID lpParam)
{
int* sharedVariable = (int*)lpParam;
while (true)
{
if (*sharedVariable == 0)
{
std::cout << "Thread 1: sharedVariable = " << *sharedVariable << std::endl;
*sharedVariable = 1;
}
}
return 0;
}
DWORD WINAPI ThreadFunction2(LPVOID lpParam)
{
int* sharedVariable = (int*)lpParam;
while (true)
{
if (*sharedVariable == 1)
{
std::cout << "Thread 2: sharedVariable = " << *sharedVariable << std::endl;
*sharedVariable = 0;
}
}
return 0;
}
int main()
{
int sharedVariable = 0;
HANDLE hThread1 = CreateThread(NULL, 0, ThreadFunction1, &sharedVariable, 0, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, ThreadFunction2, &sharedVariable, 0, NULL);
WaitForMultipleObjects(2, &hThread1, TRUE, INFINITE);
CloseHandle(hThread1);
CloseHandle(hThread2);
return 0;
}
在主函数中,我们调用了 CreateThread
函数创建了两个线程,将共享变量 sharedVariable
的地址作为参数传入。线程 1 和线程 2 都通过判断共享变量的值来实现通信,它们每当共享变量的值变化时都会输出当前的值。
在这个例子中,WaitForMultipleObjects函数将等待两个线程hThread1和hThread2完成,并且要求等待所有事件对象完成,因此参数bWaitAll的值为TRUE。并且dwMilliseconds的值为INFINITE,所以等待时间是无限的。