線程同步-讀者寫者問題(多線程)
問題描述
有讀者和寫者兩個并發進程,共享一個文件,當兩個或以上的讀進程同時訪問共享數據時不會產生副作用,
但若某個寫進程和其他進程(讀進程或寫進程)同時訪問共享數據時則可能導致數據不一致的錯誤。因此要求:
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);
}
}
運行結果如下

posted on 2022-11-09 17:13 20201321周慧琳 閱讀(69) 評論(0) 收藏 舉報
浙公網安備 33010602011771號