用信号量机制解决读者-写者问题C语言实现

这篇具有很好参考价值的文章主要介绍了用信号量机制解决读者-写者问题C语言实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章目录

  • 介绍
  • 一、什么是进程同步,进程互斥
  • 二、读者-写者问题概述
    • 1.概念图
    • 2.实例代码
  • 总结

介绍

通过实验模拟读者和写者之间的关系,了解并掌握他们之间的关系及其原理。由此增加对进程同步的问题的了解。具体如下:
  1)掌握基本的同步互斥算法,理解读者和写者模型;
  2)了解windows中多线程(多进程)的并发执行机制,线程(进程)间的同步和互斥;
  3)学习使用windows中基本的同步对象,掌握相应的API。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是进程同步,进程互斥

进程同步:对多个并发的进程在执行次序上进行协调,使其能按照一定的规则共享资源系统,使程序的执行有可在现性

进程互斥:间接相互制约关系,由于共享资源的征用问题,系统实施统一的分配,使并发的程序之间有相互制约关系

二、读者-写者问题概述

1.概念图

操作系统c语言完成读者写者问题模拟,操作系统,数据结构,c语言,c++

      调试一个采用“读写平等”策略的“读者-写者”问题的模拟程序。

利用模拟用信号量机制实现读者和写者问题:通过用户控制读进程和写进程,反应读者和写者问题中所涉及的进程的同步与互斥

 问题描述:

      模拟用信号量机制实现读者和写者问题,即有两组并发进程:读者和写者,共享一组数据区,进行读写操作,要求任一时刻“写者”最多只允许一个,而“读者”则允许多个

 规则说明:

允许多个读者同时执行读操作;

不允许读者、写者同时操作;

不允许多个写者同时操作。

问题分析:

互斥关系:写进程-写进程,读进程-写进程

设置一个p(rw),V(rw),实现对共享文件的枷锁和解锁,读进程和读进程之间要同时访问,写进程和读进程之间要互斥访问,可以让第一个读进程枷锁,最后一个读进程解锁,设置一个变量count来记录有几个读进程在访问。

写者进程:

操作系统c语言完成读者写者问题模拟,操作系统,数据结构,c语言,c++

读者进程

操作系统c语言完成读者写者问题模拟,操作系统,数据结构,c语言,c++

 

 

2.实例代码

#include<iostream>
#include<string>
using namespace std;
int r_num;//读者个数
int w_num;//写者个数
int Wmutex=1;//表示允许写或允许读
int Rcount=0;//表示正在读的进程数
int Rmutex=1;//表示对Rcount的互斥操作
int r[10]={0,0,0,0,0,0,0,0,0,0};//表示读者的状态,1表示正在读
int w[10]={0,0,0,0,0,0,0,0,0,0};//表示写者的状态,1表示正在写
int w_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//表示等待队列,0-9表示写者,10时需引入读者的等待队列,-1表示空
int r_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//读者的等待队列,0-9表示对应的读者,-1为空
void write_p(int i);//模拟写者对Wmutex的P操作,同时也作为写者进程的入口
void write(int i);//开始写操作
void write_v(int i);//模拟写者对Wmutex的V操作,写操作完成的时候调用
void radd_p(int i);//模拟读之前对Rmutex的P操作,同时也作为读者进程的入口
void radd(int i);//Rcount加1
void read_p(int i);//模拟读者对Wmutex的P操作
void radd_v(int i);//模拟读之前对Rmutex的V操作
void read(int i);//读
void rsub_p(int i);//模拟读之后对Rmutex的P操作,读操作完成的时候调用
void rsub(int i);//Rcount减1
void read_v(int i);//模拟读者对Wmutex的V操作
void rsub_v(int i);//模拟读之后对Rmutex的V操作
void write(int i)
{
	w[i]=1;
}

void write_p(int i)
{
	Wmutex--;
	if(Wmutex<0)     //表示如果Wmutex<0,则该写者进入等待队列
	{
		w_wait[-Wmutex-1]=i;
	}
	else
		write(i);
}

void write_v(int i)
{
	w[i]=0;
	Wmutex++;
	if(Wmutex<=0)    	//表示如果Wmutex<=0,则从等待队列中选择写者或读者进行操作
	{
		int k,j;
		if((w_wait[0]>=0)&&(w_wait[0]<w_num))
		{
			j=w_wait[0];
			for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];
			write(j);
		}
		else
		{		
			j=r_wait[0];
			for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];
			for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];
			radd_v(j);		
		}
	}
}

void radd_p(int i) {
	Rmutex--;
	if(Rmutex<0)         //表示如果Rmutex<0,则进入等待队列
	{
		r_wait[-Rmutex]=i;
	}
	else
		radd(i);
}

void radd(int i)
{
	Rcount++;
	if(Rcount==1)
		read_p(i);
	else
		radd_v(i);
}

void read_p(int i)
{
	Wmutex--;
	if(Wmutex<0)         //表示如果Wmutex<0,则进入等待队列
	{
		w_wait[-Wmutex-1]=10;
		r_wait[0]=i;
	}
	else
		radd_v(i);
}

void radd_v(int i)
{
	Rmutex++;
	
	if(Rmutex<=0)  //表示如果Rmutex<=0,则从等待队列中选择读者进入Rcount的临界区
	{
		int k,j;
		j=r_wait[0];
		for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];
		radd(j);
	}
	read(i);
}

void read(int i)
{
	r[i]=1;
}
void rsub_p(int i)    
{
	r[i]=0;
	Rmutex--;
	rsub(i);
}
void rsub(int i)
{
	Rcount--;
	if(Rcount==0)
		read_v(i);
	else
		rsub_v(i);
}
void read_v(int i) {
	Wmutex++;
	if(Wmutex<=0)     //表示如果Wmutex<=0,则从等待队列中选择写者或读者进行操作
	{
		int k,j;
		if((w_wait[0]>=0)&&(w_wait[0]<w_num))
		{
			j=w_wait[0];
			for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];
			write(j);
		}
		else
		{		
			j=r_wait[0];
			for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];
			for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];
			radd_v(j);		
		}
	}
	rsub_v(i);
}
void rsub_v(int i)
{
	Rmutex++;
}

int main()
{
	cout<<"请输入写者个数(1到10):";
	cin>>w_num;
	while(w_num<1||w_num>10)
	{
		cout<<"输入有误,请重新输入写者个数(1到10):";
		cin>>w_num;
	}//完成对写者个数的输入
	cout<<"请输入读者个数(1到10):";
	cin>>r_num;
	while(r_num<1||r_num>10)
	{
		cout<<"输入有误,请重新输入读者个数(1到10):";
		cin>>r_num;
	}//完成对读者个数的输入
    int x,k,j,a[20];
	while(1)
	{
		cout<<"************************************"<<endl;
		for(k=0;k<20;k++) a[k]=0;
        cout<<"Wmutex="<<Wmutex<<"Rcount="<<Rcount<<" Rmutex="<<Rmutex<<endl;
		for(k=0;k<w_num;k++)
		{
			if(w[k]==1)
				cout<<"-------写者"<<(k+1)<<"正在写"<<endl;
		}
		for(k=0;k<r_num;k++)
		{
			if(r[k]==1)
				cout<<"-------读者"<<(k+1)<<"正在读"<<endl;
		}
if(w_wait[0]==-1) cout<<"等待队列中无对象"<<endl;
		else 
		{
			cout<<"等待队列中有:";
			for(k=0;k<w_num;k++)
			{
				if(w_wait[k]==10)
					for(j=0;j<5;j++)
					{
						if(r_wait[j]!=-1)
							cout<<"-->"<<"读者"<<(r_wait[j]+1);
					}
					if((w_wait[k]>=0)&&(w_wait[k]<w_num))
						cout<<"-->"<<"写者"<<(w_wait[k]+1);
			}
			cout<<endl;
		}
			for(k=0;k<w_num;k++)
		{
			x=0;
			for(j=0;j<w_num;j++)
			{
				if(k==w_wait[j])
				{
					a[k]=1;
					x=1;
				}
			}
			if(x==1) continue;
			cout<<"("<<(k+1)<<")写者"<<(k+1);
			if(w[k]==0) cout<<"申请  ";
			else cout<<"完成  ";
		}
for(k=0;k<r_num;k++)
		{
			x=0;
			for(j=0;j<r_num;j++)
			{
				if(k==r_wait[j])
				{
					a[k+w_num]=1;
					x=1;
				}
			}
			if(x==1) continue;
			cout<<"("<<(k+1+w_num)<<")读者"<<(k+1);
			if(r[k]==0) cout<<"申请  ";
			else cout<<"完成  ";
		}
		cout<<"("<<(w_num+r_num+1)<<")结束"<<endl;
                cout<<"请输入选项序号:";
		cin>>x;
while(x<1||x>(w_num+r_num+1)||a[x-1]==1)
		{
			if(a[x-1]==1) cout<<"该对象已在等待队列中,请重新输入:";
			else cout<<"输入有误,请重新输入:";
			cin>>x;	
		}
		for(k=0;k<w_num;k++)
		{
			if(x==(k+1))
			{
				if(w[k]==0) write_p(k);
				else write_v(k);
				break;
			}
		}
		for(k=0;k<r_num;k++)
		{
			if(x==(k+1+w_num))
			{
				if(r[k]==0) radd_p(k);
				else rsub_p(k);
				break;
			}
		}
		if(x==(w_num+r_num+1)) return 0;
	}
}

总结

喜欢的话,点个关注吧文章来源地址https://www.toymoban.com/news/detail-787725.html

到了这里,关于用信号量机制解决读者-写者问题C语言实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • iOS开发进阶(六):Xcode14 使用信号量造成线程优先级反转问题修复

    应用 Xcode 14.1 进行项目编译时,遇到以下错误提示,导致APP线程暂停。 以上问题是由于iOS信号量造成线程优先级反转,在并发队列使用信号量会可能会造成线程优先级反转。 经过查询资料,发现是在 XCode14 上增加了工具,比如 : Thread Performance Checker ( XCode14 上默认开启的)

    2024年02月01日
    浏览(50)
  • 【设计模式】C语言使用共享内存和信号量,完美实现生产者与消费者模式

    生产者和消费者模式适用于生产者和消费者之间存在数据交换的场景。在这种模式中,生产者负责生产数据并将其放入缓冲区,而消费者负责从缓冲区中取出数据并进行处理。这种模式的优点是可以实现生产者和消费者之间的解耦,使得它们可以独立地进行操作,从而提高了

    2024年02月03日
    浏览(28)
  • 【Linux从入门到精通】信号量(信号量的原理与相关操作接口)详解

      本篇文章重点对 信号量的概念,信号量的申请、初始化、释放、销毁等操作进行讲解。同时举例把信号量应用到生产者消费者模型来理解 。希望本篇文章会对你有所帮助。 目录 一、信号量概念 1、1 什么是信号量 1、2 为什么要有信号量 1、3 信号量的PV操作 二、信号量的相

    2024年02月08日
    浏览(34)
  • 【Linux C | 多线程编程】线程同步 | 信号量(无名信号量) 及其使用例子

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 🤣本文内容🤣:🍭介绍 🍭 😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭 ⏰发布时间⏰: 本文未经允许,不得转发!!!

    2024年04月26日
    浏览(27)
  • 信号量Semaphore详解

    大家应该都用过 synchronized 加锁,用来保证某个时刻只允许一个线程运行。那么如果控制某个时刻允许指定数量的线程执行,有什么好的办法呢? 答案就是JUC提供的信号量 Semaphore 。 Semaphore (信号量)可以用来限制能同时访问共享资源的线程上限,它内部维护了一个 许

    2024年02月14日
    浏览(41)
  • 信号量

    信号量(semaphore)和信号只有一字之差,却是不同的概念, 信号量与之前介绍的IPC不同,它是一个计数器,用于实现进程间的互斥于同步 本文参考: Linux 的信号量_linux 信号量_行孤、的博客-CSDN博客 【Linux】Linux的信号量集_Yngz_Miao的博客-CSDN博客 Linux进程间通信(九)——信

    2024年02月12日
    浏览(37)
  • uCOSii信号量

    uCOSii 信号量 主要用来测试使用uCOSii“创建信号量,发送信号量,接收信号量,删除信号量”。 学习uCOSii一定要先了解os_cfg.h文件。 信号量管理函数如下: OSSemAccept () 无条件地等待请求一个信号量函数,中断服务子程序只能用OSSemAccept()而不能用OSSemPend(),因为中断服务子程序是不

    2024年02月07日
    浏览(45)
  • linux(信号量)

    1.回顾信号量的概念 2.认识信号量对应的操作函数 3.认识一个环形队列 4.结合sem+环形队列写生产者消费者模型 --------------------------------------------------------------------------------------------------------------------------------- 1.回顾信号量的概念  每个人想进放映厅看电影,第一件事就是买票

    2024年02月11日
    浏览(30)
  • linux信号量

    通过学习linux的信号量,对linux的信号量进行了编程。

    2024年02月10日
    浏览(32)
  • 【Linux】浅谈信号量

    tips:system V 是一套标准,共享内存,信号量,消息队列属于system V。 进程A和进程B进行通信时,假如进程A向物理内存的共享区写入\\\"Hello World\\\",但是当进程A写入了\\\"Hello\\\"时,进程B就向内存读取了,所以只读取到了\\\"Hello\\\",这就导致进程A想向进程B发送的信息,进程B读取不完整,

    2024年02月05日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包