Reader and Writer问题(写者优先)

经典操作系统问题,代码中有注释,不懂的函数可以查阅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);
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值