线程管理API
概述
线程是进程中的执行单元,同一进程的所有线程共享进程的地址空间和资源。Windows提供了完整的线程管理API。
线程创建
CreateThread - 创建线程
CreateThread函数
创建一个在调用进程的虚拟地址空间内执行的线程。
| C++ |
|---|
| HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性
SIZE_T dwStackSize, // 栈大小
LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数
LPVOID lpParameter, // 传递参数
DWORD dwCreationFlags, // 创建标志
LPDWORD lpThreadId // 线程ID
);
|
参数:
- lpThreadAttributes:安全属性,NULL表示默认
- dwStackSize:栈大小,0表示默认
- lpStartAddress:线程函数指针
- lpParameter:传递给线程函数的参数
- dwCreationFlags:
- 0:立即运行
- CREATE_SUSPENDED:创建后挂起
- lpThreadId:接收线程ID
线程函数原型:
| C++ |
|---|
| DWORD WINAPI ThreadFunction(LPVOID lpParameter);
|
示例:
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
// 线程函数
DWORD WINAPI MyThread(LPVOID param) {
int* pValue = (int*)param;
for (int i = 0; i < 5; i++) {
printf("Thread: %d, Value: %d\n", GetCurrentThreadId(), *pValue);
Sleep(1000);
}
return 0;
}
int main() {
int value = 100;
// 创建线程
DWORD threadId;
HANDLE hThread = CreateThread(
NULL, // 默认安全属性
0, // 默认栈大小
MyThread, // 线程函数
&value, // 参数
0, // 立即运行
&threadId // 线程ID
);
if (hThread == NULL) {
printf("CreateThread failed: %d\n", GetLastError());
return -1;
}
printf("Created thread: %d\n", threadId);
// 等待线程结束
WaitForSingleObject(hThread, INFINITE);
// 关闭线程句柄
CloseHandle(hThread);
return 0;
}
|
_beginthreadex - C运行时线程创建
推荐使用
使用C运行时库的线程函数更安全,可以正确初始化C运行时环境。
| C++ |
|---|
| uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
|
示例:
| C++ |
|---|
| #include <process.h>
#include <stdio.h>
unsigned WINAPI MyThread(void* param) {
printf("Thread running\n");
return 0;
}
int main() {
unsigned threadId;
HANDLE hThread = (HANDLE)_beginthreadex(
NULL, 0, MyThread, NULL, 0, &threadId
);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}
|
线程控制
OpenThread - 打开线程
| C++ |
|---|
| HANDLE OpenThread(
DWORD dwDesiredAccess, // 访问权限
BOOL bInheritHandle, // 继承标志
DWORD dwThreadId // 线程ID
);
|
访问权限:
- THREAD_ALL_ACCESS
- THREAD_TERMINATE
- THREAD_SUSPEND_RESUME
- THREAD_GET_CONTEXT
- THREAD_SET_CONTEXT
- THREAD_QUERY_INFORMATION
SuspendThread - 挂起线程
| C++ |
|---|
| DWORD SuspendThread(
HANDLE hThread
);
|
返回值:之前的挂起计数
ResumeThread - 恢复线程
| C++ |
|---|
| DWORD ResumeThread(
HANDLE hThread
);
|
示例:
| C++ |
|---|
| // 创建挂起的线程
HANDLE hThread = CreateThread(NULL, 0, MyThread, NULL, CREATE_SUSPENDED, NULL);
// 做一些初始化工作...
// 恢复线程
ResumeThread(hThread);
|
TerminateThread - 终止线程
TerminateThread函数
强制终止线程,非常危险,可能导致资源泄漏、死锁等问题。
| C++ |
|---|
| BOOL TerminateThread(
HANDLE hThread, // 线程句柄
DWORD dwExitCode // 退出代码
);
|
示例:
| C++ |
|---|
| // 不推荐使用!
TerminateThread(hThread, 1);
|
ExitThread - 退出当前线程
| C++ |
|---|
| VOID ExitThread(
DWORD dwExitCode
);
|
示例:
| C++ |
|---|
| DWORD WINAPI MyThread(LPVOID param) {
// 线程工作...
if (error) {
ExitThread(1); // 错误退出
}
return 0; // 正常退出
}
|
线程信息
GetCurrentThread - 获取当前线程句柄
| C++ |
|---|
| HANDLE GetCurrentThread();
|
GetCurrentThreadId - 获取当前线程ID
| C++ |
|---|
| DWORD GetCurrentThreadId();
|
示例:
| C++ |
|---|
| printf("Current thread ID: %d\n", GetCurrentThreadId());
|
GetThreadId - 从句柄获取线程ID
| C++ |
|---|
| DWORD GetThreadId(
HANDLE Thread
);
|
GetExitCodeThread - 获取线程退出码
| C++ |
|---|
| BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
);
|
线程优先级
GetThreadPriority - 获取线程优先级
| C++ |
|---|
| int GetThreadPriority(
HANDLE hThread
);
|
SetThreadPriority - 设置线程优先级
| C++ |
|---|
| BOOL SetThreadPriority(
HANDLE hThread,
int nPriority
);
|
优先级值:
| 优先级 |
值 |
说明 |
THREAD_PRIORITY_IDLE |
-15 |
空闲 |
THREAD_PRIORITY_LOWEST |
-2 |
最低 |
THREAD_PRIORITY_BELOW_NORMAL |
-1 |
低于标准 |
THREAD_PRIORITY_NORMAL |
0 |
标准 |
THREAD_PRIORITY_ABOVE_NORMAL |
1 |
高于标准 |
THREAD_PRIORITY_HIGHEST |
2 |
最高 |
THREAD_PRIORITY_TIME_CRITICAL |
15 |
时间关键 |
示例:
| C++ |
|---|
| SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
线程局部存储(TLS)
TlsAlloc - 分配TLS索引
TlsFree - 释放TLS索引
| C++ |
|---|
| BOOL TlsFree(
DWORD dwTlsIndex
);
|
TlsSetValue - 设置TLS值
| C++ |
|---|
| BOOL TlsSetValue(
DWORD dwTlsIndex,
LPVOID lpTlsValue
);
|
TlsGetValue - 获取TLS值
| C++ |
|---|
| LPVOID TlsGetValue(
DWORD dwTlsIndex
);
|
示例:
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
DWORD tlsIndex;
DWORD WINAPI ThreadFunc(LPVOID param) {
int value = (int)(LONG_PTR)param;
// 设置线程局部存储
TlsSetValue(tlsIndex, (LPVOID)(LONG_PTR)value);
// 获取线程局部存储
int stored = (int)(LONG_PTR)TlsGetValue(tlsIndex);
printf("Thread %d: TLS value = %d\n", GetCurrentThreadId(), stored);
return 0;
}
int main() {
// 分配TLS索引
tlsIndex = TlsAlloc();
// 创建多个线程
HANDLE threads[3];
for (int i = 0; i < 3; i++) {
threads[i] = CreateThread(NULL, 0, ThreadFunc, (LPVOID)(LONG_PTR)(i * 100), 0, NULL);
}
// 等待所有线程
WaitForMultipleObjects(3, threads, TRUE, INFINITE);
// 释放TLS索引
TlsFree(tlsIndex);
// 关闭句柄
for (int i = 0; i < 3; i++) {
CloseHandle(threads[i]);
}
return 0;
}
|
线程池
QueueUserWorkItem - 队列工作项
| C++ |
|---|
| BOOL QueueUserWorkItem(
LPTHREAD_START_ROUTINE Function,
PVOID Context,
ULONG Flags
);
|
标志:
- WT_EXECUTEDEFAULT:默认
- WT_EXECUTEINIOTHREAD:I/O线程
- WT_EXECUTEINPERSISTENTTHREAD:持久线程
- WT_EXECUTELONGFUNCTION:长时间函数
示例:
| C++ |
|---|
| DWORD WINAPI WorkItem(LPVOID param) {
printf("Work item executed in thread: %d\n", GetCurrentThreadId());
return 0;
}
QueueUserWorkItem(WorkItem, NULL, WT_EXECUTEDEFAULT);
|
线程同步对象
CreateMutex - 创建互斥体
| C++ |
|---|
| HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
|
示例:
| C++ |
|---|
| HANDLE hMutex = CreateMutex(NULL, FALSE, L"MyMutex");
WaitForSingleObject(hMutex, INFINITE);
// 临界区代码
ReleaseMutex(hMutex);
|
ReleaseMutex - 释放互斥体
| C++ |
|---|
| BOOL ReleaseMutex(
HANDLE hMutex
);
|
CreateSemaphore - 创建信号量
| C++ |
|---|
| HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
|
ReleaseSemaphore - 释放信号量
| C++ |
|---|
| BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
|
CreateEvent - 创建事件对象
| C++ |
|---|
| HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
|
SetEvent - 设置事件
| C++ |
|---|
| BOOL SetEvent(
HANDLE hEvent
);
|
ResetEvent - 重置事件
| C++ |
|---|
| BOOL ResetEvent(
HANDLE hEvent
);
|
临界区
InitializeCriticalSection - 初始化临界区
| C++ |
|---|
| void InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
|
EnterCriticalSection - 进入临界区
| C++ |
|---|
| void EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
|
LeaveCriticalSection - 离开临界区
| C++ |
|---|
| void LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
|
DeleteCriticalSection - 删除临界区
| C++ |
|---|
| void DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
|
示例:
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
CRITICAL_SECTION cs;
int counter = 0;
DWORD WINAPI ThreadFunc(LPVOID param) {
for (int i = 0; i < 1000; i++) {
EnterCriticalSection(&cs);
counter++;
LeaveCriticalSection(&cs);
}
return 0;
}
int main() {
InitializeCriticalSection(&cs);
HANDLE threads[10];
for (int i = 0; i < 10; i++) {
threads[i] = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
}
WaitForMultipleObjects(10, threads, TRUE, INFINITE);
printf("Counter: %d\n", counter);
DeleteCriticalSection(&cs);
for (int i = 0; i < 10; i++) {
CloseHandle(threads[i]);
}
return 0;
}
|
实用示例
生产者-消费者模式
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
#include <queue>
const int BUFFER_SIZE = 10;
std::queue<int> buffer;
CRITICAL_SECTION cs;
HANDLE hNotEmpty; // 事件:缓冲区非空
HANDLE hNotFull; // 事件:缓冲区未满
DWORD WINAPI Producer(LPVOID param) {
for (int i = 0; i < 20; i++) {
EnterCriticalSection(&cs);
// 等待缓冲区有空位
while (buffer.size() >= BUFFER_SIZE) {
LeaveCriticalSection(&cs);
WaitForSingleObject(hNotFull, INFINITE);
EnterCriticalSection(&cs);
}
// 生产
buffer.push(i);
printf("Produced: %d\n", i);
// 发信号:缓冲区非空
SetEvent(hNotEmpty);
ResetEvent(hNotFull);
LeaveCriticalSection(&cs);
Sleep(100);
}
return 0;
}
DWORD WINAPI Consumer(LPVOID param) {
for (int i = 0; i < 20; i++) {
EnterCriticalSection(&cs);
// 等待缓冲区有数据
while (buffer.empty()) {
LeaveCriticalSection(&cs);
WaitForSingleObject(hNotEmpty, INFINITE);
EnterCriticalSection(&cs);
}
// 消费
int item = buffer.front();
buffer.pop();
printf("Consumed: %d\n", item);
// 发信号:缓冲区未满
SetEvent(hNotFull);
ResetEvent(hNotEmpty);
LeaveCriticalSection(&cs);
Sleep(150);
}
return 0;
}
int main() {
InitializeCriticalSection(&cs);
hNotEmpty = CreateEvent(NULL, TRUE, FALSE, NULL);
hNotFull = CreateEvent(NULL, TRUE, TRUE, NULL);
HANDLE hProducer = CreateThread(NULL, 0, Producer, NULL, 0, NULL);
HANDLE hConsumer = CreateThread(NULL, 0, Consumer, NULL, 0, NULL);
WaitForSingleObject(hProducer, INFINITE);
WaitForSingleObject(hConsumer, INFINITE);
CloseHandle(hProducer);
CloseHandle(hConsumer);
CloseHandle(hNotEmpty);
CloseHandle(hNotFull);
DeleteCriticalSection(&cs);
return 0;
}
|
参考资料