操作系统读者写者问题代码实现

 

问题分析:

读者优先:

  • 读者进程执行:
    1. 无其他读者写者, 直接执行
    2. 有写者等, 但其他读者在读, 直接读
    3. 有写者写, 等待
  • 写者进程执行:
    1. 无其他读写者, 直接执行
    2. 有其他读写者, 等待

写者优先:

  • 读者进程执行:
    1. 如果此时没有写者等待, 直接执行
    2. 如果有写者等待, 那么等待
  • 写者进程执行:
    1. 如果没有其他写者, 那么执行
    2. 如果有其他读写者, 那么等待

伪代码:

读者优先:

读者R:
Wait(rmutex);
rcount++;
if(rcount == 1)
Wait(wmutex);
Signal(rmutex);
Read_Action();
Wait(rmutex);
rcount--;
if(rcount == 0)
Signal(wmutex);
Signal(rmutex);

写者W:
Wait(wmutex);
Write_Action();
Signal(wmutex);

写者优先:

int wcount=0,rcount=0;
semaphore w=1,r=1,x=1;

读者R:
reader(){
    P(r);
    P(x);
    rcount++;
    if(rcount==1)
        P(w);
    V(x);
    V(r);
    //Read()
    P(x);
    rcount--;
    if(rcount==0)
        V(w);
    V(x);
}

写者W:
writer(){
    P(x);
    wcount++;
    if(wcount==1)
        P(r);
    V(x);
    P(w);
    //Write()
    V(w);
    P(x);
    wcount--;
    if(wcount==0)
        V(r);
    V(x);
}

源码C++实现:

#include <iostream>
#include <string.h> 
#include <memory.h>
#include <windows.h> 
#include <conio.h>
#include <stdlib.h>
#include <fstream> 
#define MAX_THREAD_NUM 64 //最大线程数 
#define INTE_PER_SEC 1000 //每秒时钟中断的数目 
#define MAX_FILE_NUM 32 //最大文件数目数 
#define MAX_STR_LEN 32 //字符串的长度 
using namespace std;
int readcount = 0; //读者数目 
int writecount = 0; //写者数目 
CRITICAL_SECTION RP_Write; //临界资源 
CRITICAL_SECTION cs_Write;
CRITICAL_SECTION cs_Read;
struct ThreadInfo
{
	int serial; //线程序号 
	char entity; //线程类别(判断是读者还是写者线程) 
	double delay; //线程延迟时间 
	double persist; //线程读写操作时间 
};
//读者优先<--->读者线程//
void RP_ReaderThread(void *p) //P:读者线程信息
{
	//互斥变量 
	HANDLE h_Mutex;
	h_Mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex_for_readcount");
	DWORD wait_for_mutex; //等待互斥变量所有权 
	DWORD m_delay; //延迟时间 
	DWORD m_persist; //读文件持续时间 
	int m_serial; //线程序号 
	// 从参数中获得信息 
	m_serial = ((ThreadInfo*)(p))->serial;
	m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);
	m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);
	Sleep(m_delay); //延迟等待
	cout << "Reader thread " << m_serial << " sents the reading require !" << endl;
	//等待互斥信号,保证对 ReadCount 的访问,修改互斥 
	wait_for_mutex = WaitForSingleObject(h_Mutex, -1);
	//读者数目增加 
	readcount++;
	if (readcount == 1)
	{
		//第一个读者,等待资源 
		EnterCriticalSection(&RP_Write);
	}
	ReleaseMutex(h_Mutex); //释放互斥信
	//读文件 
	cout << "Reader thread " << m_serial << " begins to read file !" << endl;
	Sleep(m_persist);
	//退出线程 
	cout << "Reader thread " << m_serial << " finished reading file !" << endl;
	//等待互斥信号,保证对 ReadCount 的访问,修改互斥 
	wait_for_mutex = WaitForSingleObject(h_Mutex, -1);
	//读者数目减少 
	readcount--;
	if (readcount == 0)
	{
		//如果所有的读者读完,唤醒写者 
		LeaveCriticalSection(&RP_Write);
	}
	ReleaseMutex(h_Mutex); //释放互斥信号 
}
//P:写者线程信息 
void RP_WriterThread(void *p)
{
	DWORD m_delay; //延迟时间 
	DWORD m_persist; //写文件持续时间 
	int m_serial; //线程序号 
	// 从参数中获得信息 
	m_serial = ((ThreadInfo*)(p))->serial;
	m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);
	m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);
	Sleep(m_delay);
	cout << "Writer thread " << m_serial << " sents the writing require !" << endl;
	//等待资源 
	EnterCriticalSection(&RP_Write);
	//写文件 
	cout << "Writer thread " << m_serial << " begins to write file !" << endl;
	Sleep(m_persist);
	//退出线程
	cout << "Writer thread " << m_serial << " finished writing file !" << endl;
	//释放资源 
	LeaveCriticalSection(&RP_Write);
}
//读者优先处理函数
void ReaderPriority(const char *fileName)
{
	DWORD n_thread = 0; //线程数目 
	DWORD thread_ID; //线程 ID 
	DWORD wait_for_all; //等待所有线程结束 
	//互斥对象 
	HANDLE h_Mutex;
	h_Mutex = CreateMutex(NULL, FALSE, "mutex_for_readcount");
	//线程对象的数组 
	HANDLE h_Thread[MAX_THREAD_NUM];
	ThreadInfo thread_info[MAX_THREAD_NUM];
	readcount = 0; //初始化 readcount 
	InitializeCriticalSection(&RP_Write); //初始化临界区 
	ifstream inFile;
	inFile.open(fileName);
	if (!inFile)
	{
		cout << "文件打开失败!" << endl;
	}
	cout << "读者优先:" << endl;
	while (inFile)
	{
		//读入每一个读者,写者的信息 
		inFile >> thread_info[n_thread].serial;
		inFile >> thread_info[n_thread].entity;
		inFile >> thread_info[n_thread].delay;
		inFile >> thread_info[n_thread++].persist;
		inFile.get();
	}
	for (int i = 0; i < (int)(n_thread); i++)
	{
		if (thread_info[i].entity == 'R')
		{
			//创建读者进程 
			h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(RP_ReaderThread),&thread_info[i], 0, &thread_ID);
		}
		else
		{
			//创建写线程 
			h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(RP_WriterThread), &thread_info[i], 0, &thread_ID);
		}
	}

	//等待所有的线程结束 
	wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);
	cout << "All reader and writer have finished operating !" << endl;
}

 
//写者优先---读者线程 
//P:读者线程信息
void WP_ReaderThread(void *p)
{
	HANDLE print;
	print = CreateMutex(NULL, FALSE, LPCTSTR("mutex_for_print"));
	//互斥变量 
	HANDLE h_Mutex1;
	h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex1");
	HANDLE h_Mutex2;
	h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex2");
	DWORD wait_for_mutex1; //等待互斥变量所有权 
	DWORD wait_for_mutex2;
	DWORD m_delay; //延迟时间 
	DWORD m_persist; //读文件持续时间 
	int m_serial; //线程的序号 
	//从参数中得到信息 
	m_serial = ((ThreadInfo*)(p))->serial;
	m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);
	m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);
	Sleep(m_delay); //延迟等待
	DWORD wait_to_print = WaitForSingleObject(print, -1);
	cout << "Reader thread " << m_serial << " sents the reading require !" << endl;
	ReleaseMutex(print);
	wait_for_mutex1 = WaitForSingleObject(h_Mutex1, -1);
	//读者进去临界区
	EnterCriticalSection(&cs_Read);
	//阻塞互斥对象 Mutex2,保证对 readCount 的访问和修改互斥 
	wait_for_mutex2 = WaitForSingleObject(h_Mutex2, -1);
	//修改读者的数目 
	readcount++;
	if (readcount == 1)
	{
		// 如果是第 1 个读者,等待写者写完 
		EnterCriticalSection(&cs_Write);
	}
	ReleaseMutex(h_Mutex2);// 释放互斥信号 Mutex2 
	//让其他读者进去临界区 
	LeaveCriticalSection(&cs_Read);
	ReleaseMutex(h_Mutex1);
	//读文件 
	wait_to_print = WaitForSingleObject(print, -1);
	cout << "Reader thread " << m_serial << " begins to read file !" << endl;
	ReleaseMutex(print);
	Sleep(m_persist);
	//退出线程
	wait_to_print = WaitForSingleObject(print, -1);
	cout << "Reader thread " << m_serial << " finished reading file !" << endl;
	ReleaseMutex(print);
	//阻塞互斥对象 Mutex2,保证对 readcount 的访问,修改互斥
	wait_for_mutex1 = WaitForSingleObject(h_Mutex2, -1);
	readcount--;
	if (readcount == 0)
	{
		//最后一个读者,唤醒写者 
		LeaveCriticalSection(&cs_Write);
	}
	ReleaseMutex(h_Mutex2); //释放互斥信号 
}

/// 
//写者优先---写者线程 
//P:写者线程信息 
void WP_WriterThread(void *p)
{

	DWORD wait_for_mutex3; //互斥变量 
	DWORD m_delay; //延迟时间 
	DWORD m_persist; //读文件持续时间 
	int m_serial; //线程序号 
	HANDLE h_Mutex3;
	h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex3");
	//从参数中获得信息 
	m_serial = ((ThreadInfo*)(p))->serial;
	m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);
	m_persist = (DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);
	Sleep(m_delay); //延迟等待 
	cout << "Writer thread " << m_serial << " sents the writing require !" << endl;
	wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);
	writecount++; //修改写者数目 
	if (writecount == 1)
	{
		EnterCriticalSection(&cs_Read);
	}
	ReleaseMutex(h_Mutex3);
	EnterCriticalSection(&cs_Write);
	cout << "Writer thread " << m_serial << " begins to write file !" << endl;
	Sleep(m_persist);
	cout << "Writer thread " << m_serial << " finished writing file !" << endl;
	LeaveCriticalSection(&cs_Write);
	wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1);
	writecount--;
	if (writecount == 0)
	{
		LeaveCriticalSection(&cs_Read);
	}
	ReleaseMutex(h_Mutex3);
}

/ 
//写者优先处理函数 
// fileName:文件名 
void WriterPriority(const char * fileName)
{
	DWORD n_thread = 0;
	DWORD thread_ID;
	DWORD wait_for_all;
	HANDLE h_Mutex1;
	h_Mutex1 = CreateMutex(NULL, FALSE, "mutex1");
	HANDLE h_Mutex2;
	h_Mutex2 = CreateMutex(NULL, FALSE, "mutex2");
	HANDLE h_Mutex3;
	h_Mutex3 = CreateMutex(NULL, FALSE, "mutex3");
	HANDLE h_Thread[MAX_THREAD_NUM];
	ThreadInfo thread_info[MAX_THREAD_NUM];
	readcount = 0;
	writecount = 0;
	InitializeCriticalSection(&cs_Write);
	InitializeCriticalSection(&cs_Read);
	ifstream inFile;
	inFile.open(fileName);
	cout << "Writer Priority:" << endl;
	while (inFile)
	{
		inFile >> thread_info[n_thread].serial;
		inFile >> thread_info[n_thread].entity;
		inFile >> thread_info[n_thread].delay;
		inFile >> thread_info[n_thread++].persist;
		inFile.get();
	}
	for (int i = 0; i < (int)(n_thread); i++)
	{
		if (thread_info[i].entity == 'R')
		{
			//创建读者进程
			h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(WP_ReaderThread), &thread_info[i], 0, &thread_ID);
		}
		else if (thread_info[i].entity == 'W')
		{
			//创建写线程 
			h_Thread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(WP_WriterThread), &thread_info[i], 0, &thread_ID);
		}
	}
	//等待所有的线程结束 
	wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1);
	cout << "All reader and writer have finished operating !" << endl;
}
/ 
//主函数 
int main(void)
{
	system("color 3f"); //改变颜色
	const char * file = "test1.txt";
	char ch;
	while (1)
	{
		cout << "--------------------------------读者与写者问题---------------------------------" << endl;
		cout << "*******************************************************************************" << endl;
		cout << "* 1、读者优先 *" << endl;
		cout << "* 2、写者优先 *" << endl;
		cout << "* 3、退出... *" << endl;
		cout << "*******************************************************************************" << endl;
		printf("请选择(1,2,3): ");
		do {
			ch = (char)getchar();
		} while (ch != '1'&&ch != '2'&&ch != '3');
		system("cls"); //执行清屏幕命令
		switch (ch)
		{
		case '1':
			ReaderPriority(file);
			break;
		case '2':
			WriterPriority(file);
			break;
		case '3':
			return 0;
		}
		cout << endl << "按任意键继续..." << endl;
		getchar();
		system("cls");
	}
	return 0;
}

test1.txt内容:

1 R 3 5
2 W 4 5
3 R 5 2
4 R 6 5
5 W 5.1 3

结果:

 

  • 15
    点赞
  • 203
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
读者写者问题是在多线程编程中经常遇到的一类问题,它涉及到多个线程对共享资源的访问。 在读者写者问题中,有多个读者和多个写者同时访问一个共享资源,读者只需要读取资源而不修改它,写者则需要修改资源。这时就需要保证在同一时间内只能有一个写者或多个读者访问该资源,而不能让读者和写者同时访问。 为了解决这个问题,可以采用两种方法:一种是使用互斥锁来保证对共享资源的访问是互斥的;另一种是使用读写锁来允许多个读者同时访问共享资源,但在写者访问时需要排他地访问。 具体实现可以参考以下代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_rwlock_t rwlock; int shared_resource = 0; void *reader(void *arg) { int id = *(int *)arg; while (1) { pthread_rwlock_rdlock(&rwlock); printf("Reader %d read shared resource: %d\n", id, shared_resource); pthread_rwlock_unlock(&rwlock); sleep(1); } return NULL; } void *writer(void *arg) { int id = *(int *)arg; while (1) { pthread_rwlock_wrlock(&rwlock); shared_resource++; printf("Writer %d write shared resource: %d\n", id, shared_resource); pthread_rwlock_unlock(&rwlock); sleep(3); } return NULL; } int main() { pthread_t threads[5]; int i, readers[3] = {1, 2, 3}, writers[2] = {1, 2}; pthread_rwlock_init(&rwlock, NULL); for (i = 0; i < 3; i++) pthread_create(&threads[i], NULL, reader, &readers[i]); for (i = 0; i < 2; i++) pthread_create(&threads[i + 3], NULL, writer, &writers[i]); for (i = 0; i < 5; i++) pthread_join(threads[i], NULL); pthread_rwlock_destroy(&rwlock); return 0; } ``` 在这个例子中,我们创建了 3 个读者和 2 个写者线程。读者线程通过调用 `pthread_rwlock_rdlock` 函数获取读锁,写者线程通过调用 `pthread_rwlock_wrlock` 函数获取写锁。在读者线程中,我们使用共享资源的值进行输出,而在写者线程中,我们将共享资源的值加一。在每个线程中,我们使用 `sleep` 函数来模拟耗时操作。 通过使用读写锁,我们可以保证在同一时间内只有一个写者或多个读者访问共享资源。这样可以避免多个线程同时访问共享资源造成的并发问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值