7-1读者写者问题

参考https://blog.csdn.net/booksyhay/article/details/82762278
概念描述:
在一些程序中存在读者写者问题,也就是说,对某些资源的访问会 存在两种可能的情况,一种是访问必须是排它行的,就是独占的意思,这称作写操作;另一种情况就是访问方式可以是共享的,就是说可以有多个线程同时去访问某个资源,这种就称作读操作。这个问题模型是从对文件的读写操作中引申出来的。
读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状态:
1.当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞
2.当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行加锁的线程将会被阻塞
3.当读写锁在读模式的锁状态时,如果有另外的线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁的请求,这样可以避免读模式锁长期占用,而等待的写模式锁请求则长期阻塞。
读写锁最适用于对数据结构的读操作次数多于写操作的场合,因为,读模式锁定时可以共享,而写模式锁定时只能某个线程独占资源,因而,读写锁也可以叫做个共享-独占锁。
处理读者-写者问题的两种常见策略是强读者同步(strong reader synchronization)和强写者同步(strong writer synchronization). 在强读者同步中,总是给读者更高的优先权,只要写者当前没有进行写操作,读者就可以获得访问权限;而在强写者同步中,则往往将优先权交付给写者,而读者只能等到所有正在等待的或者是正在执行的写者结束以后才能执行。关于读者-写者模型中,由于读者往往会要求查看最新的信息记录,所以航班订票系统往往会使用强写者同步策略,而图书馆查阅系统则采用强读者同步策略。

解决方案:

初始化:
在这里插入图片描述
readers计数器记录房间里有多少读者。 互斥锁mutex保护共享的计数器。

osSemaphoreId_t sem_mutex;
sem_mutex = osSemaphoreNew(1, 1, NULL);

osSemaphoreId_t sem_roomEmpty;
sem_roomEmpty = osSemaphoreNew(1, 1, NULL);

int readers = 0;

void critical_writer()
{
	printf("--write\r\n");
}

void critical_reader()
{
	printf("--read\r\n");
}

写者线程:
在这里插入图片描述
读者代码类似于我们在上一节中看到的屏障代码。 我们会跟踪房间内的读者人数,以便我们可以给第一个到达的和最后一个离开的线程一个特殊的任务。

到达的第一个读者必须等待roomEmpty。 如果房间是空的,那么读者继续执行,同时禁止写者。 后续读者仍然可以进入,因为他们都不会试图在roomEmpty上等待。

如果已经有一个写者在房间里,这时有读者到了,它要等待房间变为空。 由于它拥有互斥锁,因此任何后续读者都会在互斥锁上排队。

while(1)
{
	osSemaphoreAcquire(sem_roomEmpty, osWaitForever);
	{
		critical_writer();
	}
	osSemaphoreRelease(sem_roomEmpty);
    osDelay(2000);
}

读者线程:
在这里插入图片描述
临界区之后的代码类似。 最后一个离开房间的读者把灯都关掉了-- 也就是说,它标志着roomEmpty,可能让等待的写者进入。

while(1)
{
	osSemaphoreAcquire(sem_mutex, osWaitForever);
	{
		readers++;
		if(readers == 1)
		{
			osSemaphoreAcquire(sem_roomEmpty, osWaitForever);
		}
	}
	osSemaphoreRelease(sem_mutex);

	critical_reader();

	osSemaphoreAcquire(sem_mutex, osWaitForever);
	{
		readers--;
		if(readers == 0)
		{
			osSemaphoreRelease(sem_roomEmpty);
		}
	}
	osSemaphoreRelease(sem_mutex);
}

结论:
在这里插入图片描述
代码中,特意将写的延时为2000ms,读的延时为200ms,可以看到在10个读后,有一个写。

初始条件: 1操作系统:Linux 或者 windows 2程序设计语言:C,java语言 3设有20个连续的存储单元,写入/读出的数据项按增序设定为1-20这20个字符。 要求完成的主要任务: (包括课程设计工作量及其技术要求,以及说明书撰写等具体要求) 1.技术要求: 1)为每个读者写者产生一个线程,设计正确的同步算法 2)每个读者/写者对该存储区进行操作后,即时显示该存储区的全部内容、当前指针位置和读者/写者线程的自定义标识符。。 3)读者应有3个以上,写者应有有两个以上。 4)多个读者/写者之间须共享对存储区进行操作的函数代码。 2. 设计说明书内容要求: 1)设计题目与要求 2)总的设计思想及系统平台、语言、工具等。 3)数据结构与模块说明(功能与流程图) 4)给出用户名、源程序名、目标程序名和源程序及其运行结果。(要注明存储各个程序及其运行结果的主机IP地址和目录。) 5)运行结果与运行情况 (提示: (1)连续存储区可用数组实现。 (2)编译命令可用:     cc -lpthread -o  目标文件名  源文件名 (3)多线程编程方法参见附件。) 3. 调试报告: 1) 调试记录 2) 自我评析和总结 上机时间安排: 19周一 ~ 五 下午14:00 - 18:00 (6月27日开始) 指导教师签名: 年 月 日 系主任(或责任教师)签名: 年 月 日 五、源代码 #include #include #include "fstream.h" int readcount=0; //读者数目 int writecount=0; //写者数目 CRITICAL_SECTION RP_Write; //临界区 CRITICAL_SECTION cs_Write; CRITICAL_SECTION cs_Read; struct ThreadInfo //线程信息 { int Threadhao; //线程序号 char ThreadClass; //线程类别 double ThreadStartTime; //线程开始时间 double ThreadRunTime; //线程读写持续时间 }; void ReaderFun(char* file);//读者优先函数 void R_ReaderThread(void *p);//处理读者优先读者线程 void R_WriterThread(void *p);//处理读者优先写者线程 void WriterFun(char* file); void W_ReaderThread(void *p); void W_WriterThread(void *p); int main()//主函数 { char select; while (true) { cout<<"***************本程序实现读者-写者问题*******\n"<<endl; cout<<" 1:读者优先"<<endl; cout<<" 2:写者优先"<<endl; cout<<" 3:退出"<<endl; cout<<"\n*********************************************"<<endl; cout<<"请选择要进行的操作:"<>select; if(select!='1' && select!='2' && select!='3') cout<<"你操作有误,请重试!"<<endl; }while (select!='1' && select!='2' && select!='3'); system("cls"); if (select=='3') return 0;//退出 else if (select=='1')//调用读者优先 ReaderFun("peizhi.txt"); else if(select=='2')//调用写者优先 WriterFun("peizhi.txt"); cout<<"\n是否还有继续? 1. 继续 2.退出"<>select; if(select!='1' && select!='2' ) cout<<"你操作有误,请重试!"<<endl; }while (select!='1' && select!='2'); if(select=='2') return 0;// 退出 system("cls"); } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值