常用API
函数 | 说明 | 参数 |
---|---|---|
CreateThread | 创建线程 | lpEventAttributes:安全属性,使用NULL采用默认安全属性 dwStackSize:线程堆栈大小,使用0表示采用默认大小 lpStartAddress:线程执行函数 lpParameter:给线程执行函数传入的参数 dwCreationFlags:新线程创建标志,0表示立即运行 lpThreadId:线程ID |
GetCurrentThreadId | 获取当前线程ID | |
CreateMutex | 创建互斥量 | lpMutexAttributes:安全属性,使用NULL采用默认安全属性 bInitialOwner:互斥量初始状态,True表示调用线程拥有互斥量 lpName:互斥量名称,如果为NULL表示无名称(有名称可以跨进程使用) |
ReleaseMutex | 释放互斥量 | |
CreateSemaphore | 创建信号量 | lpSemaphoreAttributes:安全属性,使用NULL采用默认安全属性 lInitialCount:信号量初始数值 lMaximumCount:信号量最大数值 lpName:信号量名称,如果为NULL表示无名称(有名称可以跨进程使用) |
ReleaseSemaphore | 增加信号量的计数 | hSemaphore:信号量句柄 lReleaseCount:信号量增加个数 lpPreviousCount:之前信号量值,使用NULL表示采用之前存储的 |
CreateEvent | 创建事件 | lpEventAttributes:安全属性,使用NULL采用默认安全属性 bManualReset:事件重置类型,TRUE为自动重置,FALSE为手动 bInitialState:初始状态,TRUE表示有状态 lpName:事件名称,如果为NULL表示无名称(有名称可以跨进程使用) |
SetEvent | 将事件对象的状态设置为 signaled | |
ResetEvent | 将事件状态重置为非 signaled | |
WaitForSingleObject | 等待单个内核对象 | hHandle:Thread、Mutex、Semaphore、Event等 dwMilliseconds:等待超时时间,INFINITE表示无限等待 |
GetExitCodeThread | 获取线程退出码 | 可以使用WaitForSingleObject等待线程退出,线程的返回值就是退出码 |
CloseHandle | 关闭句柄 | Thread、Mutex、Semaphore、Event使用完都应该关闭 |
Event、Mutex、Semaphore 区别
- Event:用于线程之间的信号通知。一个线程可以通过将事件状态设置为 signaled 来通知其他等待该事件的线程
- Mutex:用于实现临界区的互斥访问。只允许一个线程访问被互斥量保护的资源,其他线程必须等待。
- Semaphore:用于控制对一组资源的访问。信号量维护一个计数器,多个线程可以同时访问被信号量保护的资源,但是计数器的值决定了能够同时访问资源的线程数量。
生产者消费者模型
#define BUFFER_SIZE 5
typedef struct Buffer {
int data[BUFFER_SIZE];
int size;
int in;
int out;
HANDLE mutex;
HANDLE full;
HANDLE empty;
}Buffer;
static DWORD WINAPI ProducerThread(LPVOID lpParameter) {
DWORD threadId = GetCurrentThreadId();
printf("%d ProducerThread Running!\n", threadId);
Buffer* buffer = (Buffer*)lpParameter;
int index = 0;
while (true) {
WaitForSingleObject(buffer->empty, INFINITE);
WaitForSingleObject(buffer->mutex, INFINITE);
printf("write data = %d \n", index);
buffer->data[buffer->in] = index++;
buffer->in = (buffer->in + 1) % BUFFER_SIZE;
ReleaseMutex(buffer->mutex);
ReleaseSemaphore(buffer->full, 1, NULL);
Sleep(2000);
}
return 0;
}
static DWORD WINAPI ConsumeThread(LPVOID lpParameter) {
DWORD threadId = GetCurrentThreadId();
printf("%d ConsumeThread Running!\n", threadId);
Buffer* buffer = (Buffer*)lpParameter;
while (true)
{
WaitForSingleObject(buffer->full, INFINITE);
WaitForSingleObject(buffer->mutex, INFINITE);
int data = buffer->data[buffer->out];
buffer->out = (buffer->out + 1) % BUFFER_SIZE;
printf("read data = %d \n", data);
ReleaseMutex(buffer->mutex);
ReleaseSemaphore(buffer->empty, 1, NULL);
int randTime = rand() % 10000;
Sleep(2500);
}
return 0;
}
static void createProducerConsumeModel() {
Buffer* buffer = (Buffer*)malloc(sizeof(Buffer));
buffer->size = 0;
buffer->in = 0;
buffer->out = 0;
buffer->mutex = CreateMutex(NULL, false, NULL);
buffer->full = CreateSemaphore(NULL, 0, BUFFER_SIZE, NULL);
buffer->empty = CreateSemaphore(NULL, BUFFER_SIZE, BUFFER_SIZE, NULL);
DWORD dwProducerThreadId;
DWORD dwConsumeThreadId;
HANDLE hProducerThread = CreateThread(
NULL, 0, ProducerThread, buffer, 0, &dwProducerThreadId
);
HANDLE hConsumeThread = CreateThread(
NULL, 0, ConsumeThread, buffer, 0, &dwConsumeThreadId
);
printf("Create ProducerThread = %d ConsumeThread = %d \n", dwProducerThreadId, dwConsumeThreadId);
}