在windows vista 及后续的版本(Win7,Win8,Win10,Win11)中提供了对条件变量的原生支持(2006.11),为多线程程序开发带来便利。
cpp
#include <Windows.h>
#include <iostream>
#include <list>
SRWLOCK myRwLock = SRWLOCK_INIT;
CRITICAL_SECTION myCriticalSection;
CONDITION_VARIABLE myConditionVar;
class Task;
std::list<Task*> tasks;
class Task
{
public:
Task(int taskID)
{
this->taskID = taskID;
}
void doTask()
{
std::cout << "handle a task, taskID: " << taskID << ", threadID: " << GetCurrentThreadId() << std::endl;
}
private:
int taskID;
};
DWORD WINAPI consumerThread(LPVOID param)
{
Task* pTask = NULL;
while (true)
{
//AcquireSRWLockExclusive(&myRwLock);
EnterCriticalSection(&myCriticalSection);//进入临界区
while (tasks.empty())
{
//SleepConditionVariableSRW(&myConditionVar, &myRwLock, INFINITE, 0);//Flag 0:Exclusive 1:Shared,等待期间释放锁,退出等待时再次加锁
SleepConditionVariableCS(&myConditionVar, &myCriticalSection, INFINITE); //等待期间离开临界区,退出等待时再次进入临界区
}
pTask = tasks.front();
tasks.pop_front();
LeaveCriticalSection(&myCriticalSection);
//ReleaseSRWLockExclusive(&myRwLock);
if (pTask == NULL)
continue;
pTask->doTask();
delete pTask;
pTask = NULL;
}
return 0;
}
DWORD WINAPI producerThread(LPVOID param)
{
int taskID = 0;
Task* pTask = NULL;
while (true)
{
pTask = new Task(taskID);
//AcquireSRWLockExclusive(&myRwLock);
EnterCriticalSection(&myCriticalSection);//进入临界区
tasks.push_back(pTask);
std::cout << "produce a task, taskID: " << taskID << ", threadID: " << GetCurrentThreadId() << std::endl;
LeaveCriticalSection(&myCriticalSection);//离开临界区
//ReleaseSRWLockExclusive(&myRwLock);
WakeConditionVariable(&myConditionVar);
taskID++;
//休眠1秒
Sleep(1000);
}
return 0;
}
int main()
{
//初始化读写锁,也可以用读写锁配合条件变量使用
//InitializeSRWLock(&myRwLock);
//初始化临界区,本例使用临界区搭配条件变量
InitializeCriticalSection(&myCriticalSection);
//初始化条件变量
InitializeConditionVariable(&myConditionVar);
//创建5个消费者线程
HANDLE consumerThreadHandles[5];
for (int i = 0; i < 5; ++i)
consumerThreadHandles[i] = CreateThread(NULL, 0, consumerThread, NULL, 0, NULL);
//创建一个生产者线程
HANDLE producerThreadHandle = CreateThread(NULL, 0, producerThread, NULL, 0, NULL);
//等待生产者线程退出
WaitForSingleObject(producerThreadHandle, INFINITE);
//等待消费者线程退出
for (int i = 0; i < 5; ++i)
WaitForSingleObject(consumerThreadHandles[i], INFINITE);
DeleteCriticalSection(&myCriticalSection);
return 0;
}