基础知识
CreateThread
CreateThread是一个Windows API函数,用于创建一个新的线程。
函数原型如下:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
参数说明:
- lpThreadAttributes:一个指向 SECURITY_ATTRIBUTES 结构体的指针,指定了新的线程对象的安全特性。如果为NULL,则新的线程对象不能被继承。
- dwStackSize:指定新线程的堆栈大小。如果为0,则使用默认堆栈大小。
- lpStartAddress:一个指向线程函数的指针,表示新线程的入口点。
- lpParameter:传递给线程函数的参数。
- dwCreationFlags:指定了线程创建的标志位。可以为以下值之一或它们的组合:
- 0:线程立即启动并运行。
- CREATE_SUSPENDED:线程被创建挂起,不立即运行。
- lpThreadId:一个指向 DWORD 变量的指针,接收新线程的 ID。
返回值:
如果函数调用成功,则返回一个指向新创建的线程对象的句柄;否则返回NULL。
使用CreateThread函数可以创建一个新的线程对象,并将其运行在独立的执行上下文中。在调用CreateThread函数后,新线程将开始运行指定的线程函数,并且可以访问该函数中的参数。
CreateSemaphore
CreateSemaphore是一个Windows API函数,用于创建一个新的命名或未命名的信号量对象。它可以被用于控制多个线程对共享资源的访问。
函数原型如下:
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCSTR lpName
);
参数说明:
- lpSemaphoreAttributes:一个指向 SECURITY_ATTRIBUTES 结构体的指针,指定了新的信号量对象的安全特性。如果为NULL,则新的信号量对象不能被继承。
- lInitialCount:指定了信号量对象的初始计数器值。如果为0,则所有等待该信号量的线程都将进入等待状态。
- lMaximumCount:指定了信号量对象的最大计数器值。它必须大于0。
- lpName:指定了信号量对象的名称。如果为NULL,则创建未命名的信号量对象。
返回值:
如果函数调用成功,则返回一个指向新创建的信号量对象的句柄;否则返回NULL。
使用CreateSemaphore函数可以创建一个信号量对象,然后使用WaitForSingleObject或WaitForMultipleObjects函数等待信号量对象。当信号量对象计数器为0时,线程将进入等待状态,直到有另一个线程释放该信号量。使用ReleaseSemaphore函数可以增加信号量对象的计数器,并唤醒等待该信号量的线程。
GetThreadAffinityMask和SetThreadAffinityMask
GetThreadAffinityMask和SetThreadAffinityMask是Windows API提供的两个函数,用于获取和设置线程的亲和性掩码。这些函数可以用来查询和修改线程在处理器上运行的位置。
-
GetThreadAffinityMask函数:
- 函数原型:BOOL GetThreadAffinityMask(HANDLE hThread, PDWORD_PTR lpProcessAffinityMask, PDWORD_PTR lpSystemAffinityMask)
- 作用:获取指定线程的亲和性掩码信息。
- 参数:
- hThread:线程句柄,指定要查询亲和性的线程。
- lpProcessAffinityMask:指向DWORD_PTR类型的变量的指针,用于接收进程的亲和性掩码。
- lpSystemAffinityMask:指向DWORD_PTR类型的变量的指针,用于接收系统的亲和性掩码。
- 返回值:如果函数成功执行,返回非零值;如果函数执行失败,返回零。
-
SetThreadAffinityMask函数:
- 函数原型:DWORD_PTR SetThreadAffinityMask(HANDLE hThread, DWORD_PTR dwThreadAffinityMask)
- 作用:将指定线程绑定到指定的处理器核心。
- 参数:
- hThread:线程句柄,指定要设置亲和性的线程。
- dwThreadAffinityMask:DWORD_PTR类型的值,指定线程的亲和性掩码。
- 返回值:如果函数成功执行,返回之前的线程亲和性掩码;如果函数执行失败,返回0。
GetThreadAffinityMask函数用于查询指定线程的亲和性掩码信息。通过传递线程句柄以及两个指向变量的指针,可以获取该线程所绑定的处理器核心范围。lpProcessAffinityMask接收进程的亲和性掩码,lpSystemAffinityMask接收系统的亲和性掩码。这些掩码是一个位图,在位图中的每一位代表一个处理器核心,为1表示该核心可用,为0表示不可用。
SetThreadAffinityMask函数用于设置指定线程的亲和性掩码,以将线程绑定到特定的处理器核心。通过传递线程句柄和线程亲和性掩码,可以将线程限制在指定的处理器核心上运行。该函数返回之前的线程亲和性掩码,可以用来还原之前的设置。
请注意,修改线程的亲和性可能需要管理员权限,并且需要谨慎使用。不正确的使用可能导致性能问题或系统稳定性问题。
示例代码
使用Windows API提供的CreateThread函数来创建线程。下面是一个使用CreateThread函数创建线程的示例代码:
#include <iostream>
#include <windows.h>
// 全局变量
HANDLE semaphore;
DWORD_PTR affinityMask;
// 线程函数
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
// 获取线程ID
DWORD threadId = GetCurrentThreadId();
// 获取线程的处理器亲和性
DWORD_PTR oldAffinityMask;
if (!GetThreadAffinityMask(GetCurrentThread(), &oldAffinityMask, &affinityMask))
{
std::cerr << "Failed to get thread affinity mask. Error: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Thread " << threadId << " started. Affinity Mask: " << affinityMask << std::endl;
// 等待信号量
WaitForSingleObject(semaphore, INFINITE);
// 执行一些工作...
std::cout << "Thread " << threadId << " finished." << std::endl;
// 恢复线程的处理器亲和性
if (!SetThreadAffinityMask(GetCurrentThread(), oldAffinityMask))
{
std::cerr << "Failed to set thread affinity mask. Error: " << GetLastError() << std::endl;
return 1;
}
return 0;
}
int main()
{
// 创建信号量
semaphore = CreateSemaphore(NULL, 0, 1, NULL);
if (semaphore == NULL)
{
std::cerr << "Failed to create semaphore. Error: " << GetLastError() << std::endl;
return 1;
}
// 启动线程
HANDLE thread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, NULL);
if (thread == NULL)
{
std::cerr << "Failed to create thread. Error: " << GetLastError() << std::endl;
return 1;
}
// 设置线程的处理器亲和性
affinityMask = 1; // 将线程绑定到第一个处理器
if (!SetThreadAffinityMask(thread, affinityMask))
{
std::cerr << "Failed to set thread affinity mask. Error: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Thread started. Affinity Mask: " << affinityMask << std::endl;
// 发送信号量以启动线程
ReleaseSemaphore(semaphore, 1, NULL);
// 等待线程结束
WaitForSingleObject(thread, INFINITE);
// 关闭句柄
CloseHandle(thread);
CloseHandle(semaphore);
return 0;
}
在上面的示例中,我们首先创建了一个信号量 semaphore,然后使用 CreateThread 创建了一个新的线程,并将线程函数设置为 MyThreadFunction。在主线程中,我们使用 SetThreadAffinityMask 将线程绑定到第一个处理器,并发送信号量以启动线程。
在线程函数 MyThreadFunction 中,我们首先获取当前线程的 ID 和处理器亲和性,并打印到控制台。然后,我们等待信号量,执行一些工作(这里省略了具体的工作),最后恢复线程的处理器亲和性。
注意,以上示例仅为演示使用 CreateThread、CreateSemaphore、GetThreadAffinityMask 和 SetThreadAffinityMask 这些函数的基本用法。
希望对你有所帮助!
参考来源:
C++ CreateThread的使用
C++ —多线程之createthread创建线程
CreateThread函数