线程同步问题--共享资源--读者写者问题--Linux && C

线程同步问题--共享资源--读者写者问题--Linux && C,第1张

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

算法:

//伪代码 计算机 *** 作系统(第四版)西安电子科技大学出版社
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 
#include 
#include 
#include 
#include 

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 
//#include 
#include 
#include 
#include 
#include 

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


运行截图 

 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/634434.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-16
下一篇 2022-04-16

发表评论

登录后才能评论

评论列表(0条)

保存