经典操作系统问题,代码中有注释,不懂的函数可以查阅msdn
//Reader and Writer 问题,写者优先,并发读,互斥写
#include <Windows.h>
#include <stdio.h>
#include <process.h>
#include <tchar.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
volatile LONG cntR, cntW;//当前在读的reader数和当前所有的writer数目
CRITICAL_SECTION csr, csw, db;//关键段,分别控制reader、writer和对数据库的访问
CONDITION_VARIABLE cvr, cvw;//条件变量,用于SleepConditionVariableCS和WakeConditionVariable中,
//用于控制对关键段的访问
bool writing;
int val;
DWORD WINAPI ReaderThread(PVOID pvParam);//读者的线程
DWORD WINAPI WriterThread(PVOID pvParam);//写者的线程
void initRand();
int main(int argc, char **argv){
//初始化变量
HANDLE flag;
DWORD threadId;
val = 0;
writing = false;
InitializeCriticalSection(&csw);
InitializeCriticalSection(&csr);
InitializeCriticalSection(&db);
InitializeConditionVariable(&cvw);
InitializeConditionVariable(&cvr);
while (true){//循环不断产生reader和writer
srand(time(NULL));
int r = rand() % 6;
if (r % 3 == 0){
flag = CreateThread(NULL, 0, WriterThread, NULL, 0, &threadId);
if (flag)
printf("Writer thread %d created...\n", threadId);
else
printf("Error %d while creating Writer thread\n", GetLastError());
CloseHandle(flag);
}
else{
flag = CreateThread(NULL, 0, ReaderThread, NULL, 0, &threadId);
if (flag)
printf("Reader thread %d created...\n", threadId);
else
printf("Error %d while creating Reader thread\n", GetLastError());
CloseHandle(flag);
}
Sleep(1000);
}
}
DWORD WINAPI ReaderThread(PVOID pvParam){
int threadId = GetCurrentThreadId();
EnterCriticalSection(&csw);
while (cntW > 0)
SleepConditionVariableCS(&cvr, &csw, INFINITE);//确保写者优先。
//如果当前有writer在等,则不让新生成的(还未开始读)reader继续进来
LeaveCriticalSection(&csw);
EnterCriticalSection(&csr);
cntR++;
printf("This is %d reading, val = %d\n", threadId, val);
LeaveCriticalSection(&csr);
//并发读
Sleep(1500);
EnterCriticalSection(&csr);
cntR--;
if (cntR == 0)
WakeConditionVariable(&cvw);//没有reader了,唤醒writer
printf("Reader %d leaved, still %d reader(s) reading\n\n", threadId, cntR);
LeaveCriticalSection(&csr);
return 0;
}
DWORD WINAPI WriterThread(PVOID pvParam){
int threadId = GetCurrentThreadId();
EnterCriticalSection(&csw);
cntW++;//写者优先
LeaveCriticalSection(&csw);
EnterCriticalSection(&csr);
while (cntR > 0)
SleepConditionVariableCS(&cvw, &csr, INFINITE);//如果当前还有reader在读,就等所有的reader读完再写
LeaveCriticalSection(&csr);
EnterCriticalSection(&db);//互斥写
writing = true;
initRand();
val = rand();
printf("this is %d writing, val = %d\n", threadId, val);
Sleep(1500);
LeaveCriticalSection(&db);
EnterCriticalSection(&csw);
cntW--;
printf("Writer %d leaved, %d writer(s) waiting.\n\n", threadId, cntW);
if (cntW == 0)
WakeConditionVariable(&cvr);//没有writer了,唤醒reader
LeaveCriticalSection(&csw);
return 0;
}
void initRand(){
// 如果支持高性能精度计数器,则使用其初始化随机种子(微秒级)
LARGE_INTEGER nFrequency;
if (::QueryPerformanceFrequency(&nFrequency))
{
LARGE_INTEGER nStartCounter;
QueryPerformanceCounter(&nStartCounter);
srand((unsigned)nStartCounter.LowPart);
}
else // 否则使用当前系统时间初始化随机种子(毫秒级)
{
timeb stb;
ftime(&stb);
srand((unsigned)stb.millitm);
}
}