记录型信号量解决读者-写者问题

算法:
//伪代码 计算机操作系统(第四版)西安电子科技大学出版社 semaphore rmutex =
1,wmutex;//互斥信号量,解决读者和写者之间的互斥信号量wmutex //读者数量readerCount全局变量(共享资源)设置信号量rmutex
int readerCount = 0;//表示当前读者数量 //编写读者进程的操作 void Reader(){ do{
wait(rmutex);//为readerCount设置的信号量 if(readerCount == 0)wait(wmutex);//解决读者写者互斥
readerCount++; signal(rmutex); //... //perform read operation;
//操作一般要长时间,sleep(毫秒数) //... wait(rmutex); readercount--; if(readerCount ==
0)signal(wmutex); signal(rmutex); }while(TRUe); } //编写写者进程 void Writer(){ do{
wait(wmutex);//读者写者互斥冲突信号量 //... //perform write operation
//操作一般要长时间,sleep(毫秒数)模拟 //... signal(wmutex); }while(TRUE); } void main(){
cobegin() Reader(); Writer(); coend }
线程同步实现上述算法

对于线程,定义--创建初始化-线程运行函数--线程退出

对于信号量,定义--创建初始化--信号量wait和signal--信号量销毁

信号量为什么要销毁:防止资源泄密---信号量是用来解决进程互斥资源共享冲突的,那么,信号量的值可以表示当前某些进程之间共享资源的使用情况,若不销毁,随后无意中改变了信号量的值,可能会导致进程间死锁现象。

对于一个进程,可以在该进程中创建多个线程,多个线程之间共享资源,资源申请就存在互斥关系,需要有锁的概念,信号量可以实现锁。

对于写者线程pthread_t
writerTidp;定义了了该线程writerTidp,pthread_create(&writerTidp,NULL,writerThread,NULL)
创建了该线程,并指明线程函数入口是writerThread,该函数入口声明如下static void *writerThread(void
*arg);该函数具体定义如下
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] = 'a'+k;//模拟写的操作
sleep(2);//模拟写了一段时间--可以采用随机数生成这里写的时间 nowLen++; printf("\n\nWriter thread
:writing opration the global variable n equals to %d \n",n);
sleep(5);//模拟写了一段时间 sem_post(&wmutex); sleep(3); } }
看该函数writerThread前,看一下解决读者写者之间互斥冲突的semaphore信号量wmutex :

定义sem_t
wmutex;--全局变量,初始化sem_init(&wmutex,0,1),若返回-1表示线程创建失败,否则表示线程创建成功,其中的1表示wmutex的初始值,线程销毁sem_destroy(&wmutex);

该函数writerThread,先进行与读者互斥的信号量wmutex的wait操作,再进行写的操作,由于实际写操作要花一定时间,这里简单写几个字符串进去实际用时很短,采用sleep延时,若不采用延时,可能会出现一写者多读者最后发现对于读者每次只有一个人在读(运行太快,没有发生共享资源访问冲突的情况)。对于读者线程,类似。

线程同步,即算法中的
cobegin Reader(); Writer(); coend
换成代码是
void * retval; pthread_join(ReaderTidp,&retval);
pthread_join(WriterTidp,&retval);
一读者一写者且读写操作极简单的实现代码 
#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 *writerThread(void *arg); int readcount =
0; int n = 0; int main(){ pthread_t readerTidp,writerTidp; 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){
printf("pthread_create error\n"); return -2; }//init pthread
pthread_join(readerTidp,&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); printf("now the count 0f reader
is %d\n",readcount); sem_wait(&rmutex); readcount = readcount-1; if(readcount
== 0)sem_post(&wmutex); sem_post(&rmutex); } } static void *writerThread(void
*arg){ for(int i = 0;i < 10;i++) { sem_wait(&wmutex); //writer operation n =
n+1; printf("\n\nWriter thread :writing opration the global variable n equals
to %d \n",n); sem_post(&wmutex); } }
改成如下的一写者多读者的程序

代码如下
//test2.c reader-writer problem --threadiSolving // Create by Wenxin Li on
2022/04/12 //copyright © 2022 wxl_person. All rights reserved //v1.0.0.1
//ubuntu 20.04 Linux //gcc test2.c -o test2 -lpthread //./test2 #include
<stdio.h> //#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); } }
运行截图 

 

 

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信