读者-写者问题
1.问题描述
-
读者-写者问题:读者写者是一个非常著名的同步问题。读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者在读文件时写者也不去能写文件。一个数据问价或记录可以被多个进程共享,我们把只读该文件的进程称为“读者进程”,其他进程为“写者进程”。允许多个进程同时读一个共享对象,但不允许一个写者进程和其他写者进程或读者进程同时访问共享对象。即:保证一个写者进程必须与其他进程互斥的访问共享对象的同步问题;读者-写者问题常用来测试新同步原语。
-
问题分析:两类进程,一种是写者,另一种是读者。写者很好实现,因为它和其他任何进程都是互斥的,因此对每一个写者进程都给一个互斥信号量的P、V操作即可;而读者进程的问题就较为复杂,它与写者进程是互斥的,而又与其他的读者进程是同步的,因此不能简单的利用P、V操作解决。
-
问题分类:
1.读者优先算法2.写者优先算法 3.读写公平
2.代码实现
读者优先算法
- 代码:
#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;
}
- 实验结果:
写者优先
- 代码:
#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;
}
- 实验结果:
读写公平
- 代码:
#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;
}
- 实验结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!