首页 > 其他分享 >线程同步-读者写者问题(多线程)

线程同步-读者写者问题(多线程)

时间:2022-11-09 13:45:01浏览次数:47  
标签:readcount void 写者 线程 printf rmutex sem 多线程

多线程通信之读者、写者问题

读、写问题是另一个非常出名的同步问题,常常用来模拟数据库的数据查询和数据修改两种情况问题。也即,
一个数据库允许有多个访问者同时对其进行数据访问,但是对于数据的修改只能有一个。那么如何来控制这种访问多个,而修改只能一个的数据操作方式?这也涉及到线程间通信和同步问题。
数据库中存在的情况为:

读者、读者可以同时存在;
读者、写者不能同时存在,如果读者在前,则写者等待;否则所有读者等待;
写者、写者不能同时存在,先到先做,后到等待。

假设当前数据库新来了一个访问者,那么它可能的状况为以下几种:

当前数据库还没有读者、写者,那么新读者可以读;
有写者在等待,但其他读者正在读,那么新读者也可以读;
有写者在写,那么新读者等待;

假设当前数据库新来了一个写者,那么它可能的状况为以下几种:

当前数据库没有读者、写者,那么新写者可以写;
有读者在读,那新写者等待;
有写者在写,则新写者等待。

伪代码

wait (num),num是目标参数,wait的作用是使其(信息量)减一。如果信息量>=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。
signal (num),num是目标参数,signal的作用是使其(信息量)加一。 如果信息量>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。

semaphore rmutex = 1,wmutex;//互斥信号量,解决读者和写者之间的互斥信号量wmutex,为readerCount设置信号量rmutex;
int readerCount = 0;//读者数量readerCount全局变量(共享资源)
//编写读者进程的操作

点击查看代码
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(){//写者与任何进程互斥,简单的P、V操作即可实现
    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);

代码实现

点击查看代码
#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);
        }
}

运行结果:

标签:readcount,void,写者,线程,printf,rmutex,sem,多线程
From: https://www.cnblogs.com/1482156703optimus/p/16873336.html

相关文章

  • WinForm中的多线程
    使用BeginInvoke或Invoke作用在自己创建的非UI线程中,进行UI操作,比如更新UI上控件的状态。Windows窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一......
  • 多线程的操作方式
    MAX_PRIOITY10 MIN_PRIOITY 1NORM_PRIOITY 5  getPriority();返回线程的优先级setPriority(intnewPriority)改变线程的优先级......
  • 尚硅谷java入门b站零基础 异常处理 +多线程+部分项目三 2022.3.26
    380如何自定义异常/**如何自定义异常类?*1.继承于现有的异常结构:RuntimeException、Exception*2.提供全局常量:serialVersionUID*3.提供重载的构造器**/publicc......
  • 线程同步-读者写者问题(多线程)
    任务描述:0推荐在openEuer上实现1描述操作系统中“读者-写者”问题,理解问题的本质,提交你理解或查找到的文本资料2利用多线程完成reader和writer3在main中测试若干个......
  • js线程机制与事件机制
    基于尚硅谷的尚硅谷JavaScript高级教程提供笔记撰写,加入一些个人理解github源码博客下载线程与进程进程程序的一次执行,它占有一片独有的内存空间可以通过windows......
  • Linux多线程开发
    1.线程线程概述与进程(process)类似,线程(thread)是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享......
  • 从排队上厕所来看线程池的线程分配和处理
      德州站旁边,王二经营一家厕所服务公司,为公众提供便民入厕服务。车站每天人来人往。人越多,自然,王二的生意就越好。王二这里固定提供3间厕所,当超过3人用厕时,后面的人就排队......
  • day 22- 线程的礼让,优先级,守护线程
    线程的礼让利用Thread.yield()使线程进行礼让礼让的概念:礼让线程,让当前正在执行的线程暂停,但并不是阻塞将线程从运行状态转化为就绪状态线程礼让是由cpu调度,并......
  • 读者-写者(多线程)
    目录问题描述问题分析伪代码伪代码描述相关函数代码实现问题描述有读者和写者两个并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某......
  • SimpleDateFormat线程安全问题排查
    一.问题现象运营部门反馈使用小程序配置的拉新现金红包活动二维码,在扫码后跳转至404页面。二.原因排查首先,检查扫码后的跳转链接地址不是对应二维码的实际URL,根据代......