首页 > 其他分享 >读者-写者问题(多线程)

读者-写者问题(多线程)

时间:2022-11-13 20:12:26浏览次数:54  
标签:readcount 写者 互斥 读者 printf sem 多线程

"读者-写者"问题

实现读者和写者问题是一个经典的并发程序设计问题,是经常出现的一种同步问题。所谓读者写者问题,是指保证一个写进程必须与其他进程互斥地访问共享对象的同步问题

读写操作限制

可以有一个或多个数量的读进程同时读这个文件;一次只有一个写进程可以写文件;若一个写进程正在写文件,则禁止任何读进程读文件;即读读允许、读写互斥、写写互斥

在“读者-写者”问题中,使用读者优先和写者优两种解决方案

  • 在读者优先策略中,读进程具有优先权,也就是说,当至少有一个读进程在读时,随后的读进程就无需等待,可以直接开始读操作,此过程中写进程可能会饥饿。
  • 在写者优先策略中,写进程具有优先权,写者优先与读者优先类似。不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作,读者必须等到没有写者处于等待状态才能开始读操作。

需要满足的条件

  1. 允许多个读者可以同时对文件执行读操作
  2. 只允许一个写者往文件中写信息
  3. 任一写者在完成写操作之前不允许其他读者或写者工作
  4. 写者执行写操作前,应让已有的读者和写者全部退出

过程分析

  1. 关系分析

    1. 读者和写者是互斥的,写者和写者也是互斥的
    2. 读者和读者不存在互斥问题
  2. 整理思路

    两个进程,即读者和写者

    1. 写者是比较简单的,它和任何进程互斥,用互斥信号量的 P操作、V操作即可解决。
    2. 读者的问题比较复杂,它必须实现与写者互斥的同时还要实现与其他读者的同步,因此,仅仅简单的一对 P操作、V操作是无法解决的。那么,在这里用到了一个计数器,用它来判断当前是否有读者读文件。当有读者的时候写者是无法写文件的,此时读者会一直占用文件,当没有读者的时候写者才可以写文件。同时这里不同读者对计数器的访问也应该是互斥的
  3. 信号量设置

    1. 首先设置信号量 count 为计数器,用来记录当前读者数量,初值为 0
    2. 设置 mutex 为互斥信号量,用于保护更新 count 变量时的互斥
    3. 设置互斥信号量 rw 用于保证读者和写者的互斥访问

算法描述

读者优先

为实现读者与写者进程间在读或写时的互斥而设置了一个互斥信号量filesrc,表示对资源的申请。当写者发出写请求时,必须先申请到资源,以此来实现读写互斥。另外,再设置一个整型变量readcount表示正在读的进程数目。由于只要有一个读进程Reader在读,便不允许写进程Writer去写。因此,仅当readcount=0,表示尚无Reader进程在读时,Reader进程才需要执行wait(filesrc)操作。若wait(filesrc)操作成功,Reader进程便可开始读,相应地,做readcount+1操作。同理,仅当Reader进程在执行了readcount减1操作后其值为0时,才须执行signal(filesrc)操作,以便让Writer进程进行写操作。又因为readcount是一个可被多个Reader进程访问的临界资源,因此,也应该为它设置一个互斥信号量rcsignal。

写者优先

写者操作和读者操作相似,为实现读者与写者进程间在读或写时的互斥而设置了一个互斥信号量wrt,表示对资源的申请。读者写者等待进程数量通过记录当前堵塞的写者进程,与当前在读的读者进程数,所以引入readerCount与writerCount;写者操作要求有写者到来时应让写者先写。因此定义一个整型变量writercount,用来记录写者的数目,当writercount=0时才可以释放读者进行读操作。相应的,因为ReaderCount与WriterCount也是可以被多个读者、写者进程访问的临界资源,因此也需要设置互斥信号量RCSignaI与writeCountSignal。

互斥信号量read_s保证进程优先互斥,首先在读操作中申请读取资源,在执行读取操作代码之前释放该资源,同时在写操作中如果writercount 的值为 0,申请读取该资源,用于第一位写者申请资源,写操作完成后释放资源。该操作的作用是当写操作申请到该资源时,占用其直至写者堵塞排队队列都完成写操作,即会将所有读操作阻塞,以达到写者插队的效果。

运行效果

代码实现

实现多读者(多线程)操作

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
 
sem_t rmutex,wmutex;
static void *readerThread(void *arg);
static void *reader3Thread(void *arg);
static void *reader2Thread(void *arg);
static void *writerThread(void *arg);
int readcount = 0;
int n = 0;
int nowLen = 1;
char contentArticle[10][100];
int main(){
 
	pthread_t readerTidp,writerTidp,reader3Tidp,reader2Tidp;
	void *retval;
	
	if(sem_init(&rmutex,0,1)==-1||sem_init(&wmutex,0,1)==-1){
		printf("sem_init error\n");
		return -1;
	}//init semaphore
 
	if(pthread_create(&readerTidp,NULL,readerThread,NULL) !=0||pthread_create(&writerTidp,NULL,writerThread,NULL) !=0||pthread_create(&reader3Tidp,NULL,reader3Thread,NULL) !=0||pthread_create(&reader2Tidp,NULL,reader2Thread,NULL) !=0){
		printf("pthread_create error\n");
		return -2;
	}//init pthread
 
	pthread_join(readerTidp,&retval);
	pthread_join(reader3Tidp,&retval);
	pthread_join(reader2Tidp,&retval);
	pthread_join(writerTidp,&retval);
 
	sem_destroy(&rmutex);
	sem_destroy(&wmutex);
	return 0;
}
 
static void *readerThread(void *arg){
	for(int i = 0;i < 10;i++)
	{
		sem_wait(&rmutex);
		if(readcount == 0)sem_wait(&wmutex);
		readcount = readcount+1;
		sem_post(&rmutex);
	
		//read operatiom
		printf("\n\nI'm reader first Reader thread :...the global variable  n equals to %d\n",n);
		for(int j = 0;j < nowLen-1;j++)
		{
			for(int k = 0;k < 26;k++)
				printf("%c",contentArticle[j][k]);
			printf("\n");
		}
			printf("now the count 0f reader is %d\n",readcount);
		printf("now the length 0f content is %d\n",nowLen-1);
		sleep(5);
 
		sem_wait(&rmutex);
		readcount = readcount-1;
		if(readcount == 0)sem_post(&wmutex);
		sem_post(&rmutex);
		sleep(1);
	}
}
 
static void *reader3Thread(void *arg){
        for(int i = 0;i < 10;i++)
        {
                sem_wait(&rmutex);
                if(readcount == 0)sem_wait(&wmutex);
                readcount = readcount+1;
                sem_post(&rmutex);
 
                //read operatiom
                printf("\n\nI'm reader third  Reader thread :...the global variable  n equals to %d\n",n);
		for(int j = 0;j < nowLen-1;j++)
                {
                      for(int k = 0;k < 26;k++)
                                printf("%c",contentArticle[j][k]);
                        printf("\n");
                }
                printf("now the count 0f reader is %d\n",readcount);
                printf("now the length 0f content is %d\n",nowLen-1);
 
		sleep(5);
                sem_wait(&rmutex);
                readcount = readcount-1;
                if(readcount == 0)sem_post(&wmutex);
                sem_post(&rmutex);
                sleep(8);
        }
}
 
 
static void *reader2Thread(void *arg){
        for(int i = 0;i < 10;i++)
        {
                sem_wait(&rmutex);
                if(readcount == 0)sem_wait(&wmutex);
                readcount = readcount+1;
                sem_post(&rmutex);
 
                //read operatiom
                printf("\n\nI'm reader second Reader thread :...the global variable  n equals to %d\n",n);
		for(int j = 0;j < nowLen-1;j++)
              {
                        for(int k = 0;k < 26;k++)
                                printf("%c",contentArticle[j][k]);
                        printf("\n");
                }
 
                printf("now the count 0f reader is %d\n",readcount);
                printf("now the length 0f content is %d\n",nowLen-1);
 
 
                sem_wait(&rmutex);
                readcount = readcount-1;
                if(readcount == 0)sem_post(&wmutex);
                sem_post(&rmutex);
                sleep(4);
        }
}
 
 
 
static void *writerThread(void *arg){
        for(int i = 0;i < 10;i++)
        {
                sem_wait(&wmutex);
              
	       	//writer operation 
	       	n = n+1;
		for(int k = 0;k < 26;k++)
		contentArticle[nowLen-1][k] = 'z'-k;
		nowLen++;
		printf("\n\nWriter thread :writing opration the global variable  n equals to  %d \n",n);
                sleep(2);
	       	sem_post(&wmutex);
                sleep(3);
        }
}

标签:readcount,写者,互斥,读者,printf,sem,多线程
From: https://www.cnblogs.com/cqszxy2020/p/16886769.html

相关文章

  • 读者-写者(多线程)
    题目1描述操作系统中“读者-写者”问题,理解问题的本质,提交你理解或查找到的文本资料2利用多线程完成reader和writer3在main中测试若干个reader和writer的测试,提交......
  • 读者-写者(多线程)
    任务详情1描述操作系统中“读者-写者”问题,理解问题的本质,提交你理解或查找到的文本资料2利用多线程完成reader和writer3在main中测试若干个reader和writer的测试,......
  • 多线程编程学习笔记文章目录
     多线程编程学习笔记-基础(一)多线程编程学习笔记-基础(二)多线程编程学习笔记-基础(三) 多线程编程学习笔记——线程同步(一)多线程编程学习笔记——线程同步(二) 多线......
  • C#多线程之同步基础篇
    目录一、基本概念二、锁构造MonitorMutex死锁三、信号构造SemaphoreManualResetEventAutoResetEventCountdownEvent四、等待句柄等待句柄和线程池WaitHandle一、基本概念......
  • 读者-写者(多线程)
    读者-写者(多线程)描述问题:需满足的条件:1.写进程与写进程之间必须互斥的写入数据(因为如果两个写进程同时对共享数据中的区域A中的数据进行写操作的话,会导致数据错误覆盖......
  • 如何解决多线程安全问题一
    packagedeep;//问题:出现重票和错票(即线程安全问题)//原因:某个线程操作车票的过程中,未完成时其它线程就参与进来,也操作//如何解决:a操作完才允许其它线程加入//在java中通过......
  • Java多线程中锁的理解与使用
    参考:https://blog.csdn.net/tyyj90/article/details/782360531.简介锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如synchronized和ReentrantLock等)......
  • C# 使用CancellationTokenSource取消多线程
    原文网址:https://blog.csdn.net/xwnxwn/article/details/115670973如下:我们点击一个按钮开启线程,然后点击取消按钮取消该线程的执行    CancellationTokenSourcect......
  • 统计开始目录及其子目录下的指定类型文件中的单词(使用多线程、并发多线程(mappedReduce
    #include<QList>#include<QMap>#include<QTextStream>#include<QString>#include<QStringList>#include<QDir>#include<QElapsedTimer>#include<QApplicati......
  • Java静态代理设计模式模式(多线程Runnable)
    静态代理设计模式,就是代理对象来帮你忙前忙后,你负责出席一下就好了。需要:1.实现相同的接口2.真实角色3.代理角色,里面有一个成员是接口对象(实际上是真实角色----接口实......