问题描述
有读者和写者两个并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,
但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:
1、允许多个读者可以同时对文件进行读操作;
2、只允许一个写者往文件中写信息;
3、任一写者完成之前不允许其他读者或写者工作;
4、写者执行写操作前,应让已有的读者和写者全部退出。
-
关系分析。由问题分析,读者和写者是互斥的,写者和写者也是互斥的,而读者和读者不存在互斥问题。
-
整理思路。两个进程,即读者和写者。写者是比较简单的,它和任何进程互斥,用互斥信号量的P、V操作即可解决。读者的问题比较复杂,它必须在实现与写者互斥的同时,实现与其他读者的同步,因此简单的一对P、V操作是无法解决问题的。需要用到一个计时器,用来判断当前是否有读者读文件。当有读者读文件时,写者是无法写文件的,此时读者会一直占用文件,当没有读者时,写者才可以写文件。同时,不同的读者对于计时器的访问也应该是互斥的。
-
信号量设置。首先设置信号量readerCount为计数器,用于记录当前读者的数量,初值为0;设置mutex为互斥信号量,用于保护更新count变量时的互斥;设置互斥信号量rmutex,wmutex,用于保证读者和写者的互斥访问。
读者优先
初始化
写者
读者
写者优先
初始化
读者
写者
代码实现
#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);
}
}
运行结果如下