读者-写者(多线程)

读者-写者(多线程)

读者写者问题

抽象解释

  • 多个进程访问一个共享的数据区
  • 读者(读进程)只能读数据,写者(写进程)只能写数据
  • 适用于数据库、文件、内存、寄存器等数据区的访问模型
  • 如12306购票系统,由于用户量庞大和数据量巨大,不可避免地会出现多个进程同时查询(读)或修改(写)同一条数据的情况

读者写者问题的三个约束条件

  • 读者之间不互斥(你和室友可以同时查看元旦那天早上7点的高铁信息)
  • 写者之间必须互斥(你和室友不能同时申请购买元旦那天早上七点G1234的6D号位置)
  • 读者写者之间也互斥(假如你正在买G1234的6D座位,你的室友无法读到该位置的售票信息)

读者写者问题VS生产者消费者问题

  • 能不能用生产者消费者问题解决读者写者问题?

  • 不能,像生/消问题那样严格互斥读者写者虽然可以保证数据的正确,却无法实现同时读的特点

  • 如何判断一个问题是生产者消费者问题,还是读者写者问题?

生产者消费者问题:数据消费后就没有了;读者写者问题:数据可多次读
生产者消费者问题:消费者彼此互斥;读者写者问题:读者可以同时读

解决读者写者问题的三种方案

策略一 读者优先
  • 有读者在读的话,随后的读者可以进入临界区一起读
  • 待临界区全部读者退出后再轮到下一个写者
  • 有越过写者的现象,造成写者饥饿
变量设置
  • wsem:互斥信号量
  • readcount:统计同时读的readers
  • x:对readcount的修改加锁

参考资料https://blog.csdn.net/HBBBOY/article/details/108125682
https://blog.csdn.net/qq_44722674/article/details/111570073

#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);
        }
}

posted @ 2022-11-09 14:47  20201327刘谨铭  阅读(31)  评论(0编辑  收藏  举报