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

读者-写者(多线程)

时间:2022-11-11 11:22:40浏览次数:43  
标签:多线程 int wmutex 写者 读者 rmutex sem include post

1. 描述操作系统中“读者-写者”问题,理解问题的本质,提交你理解或查找到的文本资料

问题描述:

image

  • 多个进程访问一个共享的数据区
  • 读者(读进程)只能读数据,写者(写进程)只能写数据
  • 适用于数据库、文件、内存、寄存器等数据区的访问模型

需要满足的条件:

  1. 写进程与写进程之间必须互斥的写入数据(因为如果两个写进程同时对共享数据中的区域A中的数据进行写操作的话,会导致数据错误覆盖的问题)

  2. 写进程与读进程之间必须互斥的访问共享数据(因为写进程与读进程如果同时访问共享数据,可能会导致数据不一致的问题。比如:读进程A想要访问共享数据中的B数据,但是写进程C在读进程A访问B数据之前将B数据进行了更新,这就会导致读进程A读不到它想要读到的数据,从而出现数据不一致问题)

  3. 读进程与读进程之间可以同时访问数据,不需要实现互斥的访问共享数据(因为读进程读数据,并不会像之前的生产者消费者问题中的消费者那样改变数据或者是将数据清空,所以多个读进程可以同时访问共享数据)

2. 利用多线程完成reader 和writer

有两种不同的线程调度方式,分别是:

读者优先:

读者就是优先的。假设a,b都是同时请求,但是a是读者那么a优先使用资源,还有一点很重要的就是读者优先的读者可以并行执行。而写着只能单线程执行。在执行过程中,只要阻塞的写者在等待过程中有新的读者进来那么他要等待所有读者完成才能自己释放自己。
image
image

写者优先:

无疑所有写的操作是优先的,这个过程可能会产生大量阻塞,因为相对较快(本来可以并行的读者被大量阻塞)。如果资源中没有写者那么读者依然可以并行,但是一旦出现写者在等待读者资源,那么新的读者就不能在并行执行,要等待所有写者执行完毕才可执行读者。
image

image

3. 在main中测试若干个reader 和writer的测试,提交截图说明代码的正确性

读者优先:

image

点击查看代码
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
 
#define N 5
 
int count=0,a=5,b=5;
int r[N]={0,1,2,3,4};
sem_t wmutex,rmutex;
 
 
void delay()
{
	int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒           
	usleep(time * 100000);
}
 
void Reader(void *arg)
{
	int i=*(int *)arg;
	while(a>0)
	{
    		a--;
    		delay();
        	sem_wait(&rmutex);
        	if(count==0)
        	    sem_wait(&wmutex);
        	count++;
        	sem_post(&rmutex);
	
        	printf("Reader%d is reading!\n",i);
        	printf("Reader%d reads end!\n",i);
        	
        	sem_wait(&rmutex);
        	count--;
        	if(count==0)
        	    sem_post(&wmutex);
        	sem_post(&rmutex);
    	}	
}
 
void Writer()
{
	while(b>0)
    	{
    		b--;
    		delay();
        	sem_wait(&wmutex);
    		
    		printf("writer is writing!\n");
        	printf("writer writes end!\n");
    		
        	sem_post(&wmutex);
    	}
}
 
int main()
{
	int i;
	pthread_t writer,reader[N];
	srand((unsigned int)time(NULL));
	
	sem_init(&wmutex,0,1);//互斥锁初始化 
	sem_init(&rmutex,0,1);
	
	for(i=0;i<5;i++)//创建线程 
	{
		pthread_create(&reader[i],NULL,(void *)Reader,&r[i]);
	} 
	
	pthread_create(&writer,NULL,(void *)Writer,NULL);
		
	pthread_join(writer,NULL);//线程等待 
	
	sem_destroy(&rmutex);   //互斥锁的销毁
	sem_destroy(&wmutex);   
	
	return 0;
} 

写者优先:

image

点击查看代码
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
 
#define N 5
 
int readcount=0,writecount=0,a=5,b=2;
int r[N]={0,1,2,3,4};
int w[N]={0,1};
sem_t wmutex,rmutex,mutex1,num;
 
 
void delay()
{
	int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒           
	usleep(time * 100000);
}
 
void Reader(void *arg)
{
	int i=*(int *)arg;
	while(a>0)
	{
    		a--;
    		delay();//延迟 
    		
		//进入共享文件前的准备 
    		sem_wait(&num);//在无写者进程时进入 
        	sem_wait(&rmutex);//与其他读者进程互斥的访问readcount 
        	if(readcount==0)
        		sem_wait(&mutex1);//与写者进程互斥的访问共享文件 
        	readcount++;
        	sem_post(&rmutex);
        	sem_post(&num); 
	
		//reader
        	printf("Reader%d is reading!\n",i);
        	printf("Reader%d reads end!\n",i);
        	
        	//退出共享文件后的处理 
        	sem_wait(&rmutex);
        	readcount--;
        	if(readcount==0)
        		sem_post(&mutex1);
        	sem_post(&rmutex);
    	}	
}
 
void Writer(void *arg)
{
	int i=*(int *)arg;
	while(b>0)
    	{
    		b--;
    		delay();
    		
    		//进入共享文件前的准备 
    		sem_wait(&wmutex);//保证多个写者进程能够互斥使用writecount 
    		writecount++;
    		if(writecount==1)
    			sem_wait(&num);//用于禁止读者进程 
    		sem_post(&wmutex);
    		
    		//writer
        	sem_wait(&mutex1);//与其他所有进程互斥的访问共享文件 	
    		printf("writer%d is writing!\n",i); 
        	printf("writer%d writes end!\n",i);
    		sem_post(&mutex1);
        	
        	//退出共享文件后的处理 
        	sem_wait(&wmutex);
    		writecount--;
    		if(writecount==0)
    			sem_post(&num);
    		sem_post(&wmutex);
    	}
}
 
int main()
{
	int i;
	pthread_t writer[N],reader[N];
	srand((unsigned int)time(NULL));
	
	sem_init(&wmutex,0,1);//互斥锁初始化 
	sem_init(&rmutex,0,1);
	sem_init(&mutex1,0,1);	
	sem_init(&num,0,1);
	
	for(i=0;i<5;i++)//创建线程 
	{
		pthread_create(&reader[i],NULL,(void *)Reader,&r[i]);
	} 
	
	for(i=0;i<2;i++)//创建线程 
	{
		pthread_create(&writer[i],NULL,(void *)Writer,&w[i]);
	}
	
	for(i=0;i<2;i++)//等待线程 
	{
		pthread_join(writer[i],NULL);
	}
	
	for(i=0;i<5;i++)//等待线程 
	{
		pthread_join(reader[i],NULL);
	}	
	
	sem_destroy(&rmutex);   //互斥锁的销毁
	sem_destroy(&wmutex);   
	sem_destroy(&mutex1);
	sem_destroy(&num);
	
	return 0;
} 

读写平等:

image

点击查看代码
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
 
#define N 5
 
int readcount=0,a=5,b=5;
int r[N]={0,1,2,3,4};
sem_t wmutex,rmutex,queue;
 
 
void delay()
{
	int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒           
	usleep(time * 100000);
}
 
void Reader(void *arg)
{
	int i=*(int *)arg;
	while(a>0)
	{
    		a--;
    		delay();
    		
			sem_wait(&queue);		//让写者进程排队,读写进程具有相同的优先级 
        	sem_wait(&rmutex);		//与其他读者进程互斥的访问readcount 
        	if(readcount==0)		//最开始的时候readcount=0 
        		sem_wait(&wmutex);	//与写者进程互斥的访问共享文件 
        	readcount++;
        	sem_post(&rmutex);
			sem_post(&queue);		//使得写者进程进入准备状态 
	
			//Reader
        	printf("Reader%d is reading!\n",i);
        	printf("Reader%d reads end!\n",i);
        	
        	sem_wait(&rmutex);
        	readcount--;
        	if(readcount==0)
        	    sem_post(&wmutex);
        	sem_post(&rmutex);
    	}	
}
 
void Writer()
{
	while(b>0)
    	{
    		b--;
    		delay();
    		
    		sem_wait(&queue); 
        	sem_wait(&wmutex);
    		
    		printf("writer is writing!\n");
        	printf("writer writes end!\n");
    		
        	sem_post(&wmutex);
        	sem_post(&queue);
    	}
}
 
int main()
{
	int i;
	pthread_t writer,reader[N];
	srand((unsigned int)time(NULL));
	
	sem_init(&wmutex,0,1);//互斥锁初始化 
	sem_init(&rmutex,0,1);
	sem_init(&queue,0,1);
	
	for(i=0;i<5;i++)//创建线程 
	{
		pthread_create(&reader[i],NULL,(void *)Reader,&r[i]);
	} 
	
	pthread_create(&writer,NULL,(void *)Writer,NULL);
		
	pthread_join(writer,NULL);//线程等待 
	
	sem_destroy(&rmutex);   //互斥锁的销毁
	sem_destroy(&wmutex);   
	sem_destroy(&queue); 
	
	return 0;
} 

标签:多线程,int,wmutex,写者,读者,rmutex,sem,include,post
From: https://www.cnblogs.com/charliecza/p/16879980.html

相关文章

  • Java多线程 CompletionService和ExecutorCompletionService
    目录​​一、说明​​​​二、理解​​​​三、实现​​​​1.使用Future​​​​2.使用ExecutorCompletionService​​​​3.take()方法​​​​4.poll()方法​​​​5.pol......
  • Java多线程 Callable和Future
    目录​​一、说明​​​​二、理解​​​​三、实现​​​​1.实现接口​​​​2.执行线程​​一、说明Java提供了三种创建线程的方法实现​​Runnable​​接口继承​​T......
  • Java多线程 Future和FutureTask的区别
    目录​​一、说明​​​​二、理解​​​​三、实现​​​​1.实现接口​​​​2.使用Future​​​​3.使用FutureTask​​一、说明Future和FutureTask的关系Future是一个......
  • Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略
    目录​​一、说明​​​​二、理解​​​​三、实现​​​​1.AbortPolicy​​​​2.DiscardPolicy​​​​3.DiscardOldestPolicy​​​​4.CallerRunsPolicy​​​​5.自......
  • Java多线程 线程池Executor框架
    目录​​一、说明​​​​二、理解​​​​Executor​​​​ExecutorService​​​​Executors​​​​三、实现​​​​1.newSingleThreadExecutor​​​​2.newFixedThr......
  • python 多线程
     示例1importthreadingimporttime#进程比较消耗资源线程比较消耗cpudeffunc01(number):print("函数func01start")time.sleep(2)print("函......
  • 读者写者多线程
    读者写者1.描述操作系统中“读者-写者”问题,理解问题的本质,提交你理解或查找到的文本资料读者写者问题可分为读者优先、读写公平、写者优先三种,无论是其中哪一种,在没有程......
  • Linux网络通信(TCP套接字编写,多进程多线程版本)
    预备知识源IP地址和目的IP地址IP地址在上一篇博客中也介绍过,它是用来标识网络中不同主机的地址。两台主机进行通信时,发送方需要知道自己往哪一台主机发送,这就需要知道接......
  • Java多线程
    一、创建多线程1.实现Runnable接口2.继承Thread类3.匿名类Runnable与Thread区别:一个是接口一个是类二、线程安全的类1.HashMap和Hashtable都实现了Map接口,都是键值对......
  • java 多线程Callable,有返回值多线程, 当线程获取到需要的值,则停止其他线程,直接输出结
    使用Callable进行多线程处理数据。当处理大批量的数据时,若某个线程返回需要的值则终止其他线程并输出结果。下面是我自己结合Callable具有返回值的线程,和CyclicBarrier......