PV经典问题之读写者问题

问题描述

有一个许多进程共享的数据区,这个数据区可以是一个文件或者主存 的一块空间;有一些只读取这个数据区的进程(Reader)和一些只往数据区写数据的进 程(Writer),此外还需要满足以下条件:
(1)任意多个读进程可以同时读这个文件;
(2)一次只有一个写进程可以往文件中写;
(3)如果一个写进程正在进行操作,禁止任何读进程度文件。

读者优先算法

关系分析:由题⽬分析可知,读者和写者是互斥的,写者和写者也是互斥的,⽽读者和读者不存在互斥问题。

整理思路:写者是⽐较简单的,它与任何线程互斥,⽤互斥信号量的 PV 操作即可解决。读者的问题⽐较复杂,它 必须实现与写者的互斥,多个读者还可以同时读。所以,在这⾥⽤到了⼀个计数器,⽤它来判断当前是否有读者读 ⽂件。当有读者的时候写者是⽆法写⽂件的,此时读者会⼀直占⽤⽂件,当没有读者的时候写者才可以写⽂件。同 时,不同的读者对计数器的访问也应该是互斥的。

故问题完整解答如下(读进程优先算法):
设置⼀个计数变量count,⽤来记录当前的读者数量,初值为0;
设置互斥信号量mutex,⽤于保护更新count变量时的互斥,初值为1;
设置互斥信号量rw⽤于保证读者和写者的互斥访问,初值为1。

int count = 0;                  //⽤用于记录当前的读者数量量 

semaphore mutex = 1;            //⽤用于保护更更新count变量量时的互斥 semaphore rw = 1;               //⽤用于保证读者和写者互斥地访问⽂文件 

writer () {                     //写者进程
        while (1) {        
        P(rw);                  //互斥访问共享⽂文件        
        Writing;                //写⼊入        
        V(rw);                 //释放共享⽂文件    
	}
}

reader () {                     // 读者进程
    while (1) {
	P(mutex);               //互斥访问count变量量        
	if (count == 0) {       //当第⼀一个读进程读共享⽂文件时            				 
		 P(rw);              //阻⽌止写进程写 
	}
	 count++;                //读者计数器器加1        
	 V(mutex);               //释放互斥变量量count        
	 reading;                //读取        
	 P(mutex);               //互斥访问count变量量       
	 count--;                //读者计数器器减1        
	 if (count == 0) {       //当最后⼀一个读进程读完共享⽂文件 	
	 	V(rw);              //允许写进程写  
	 }
	  V(mutex);               //释放互斥变量量count 
	}
}

问题解答分析: 在上⾯的算法中,读进程是优先的,也就是说,当存在读进程时,写操作将被延迟,并且只要有⼀个读进程 活跃,随后⽽来的读进程都将被允许访问⽂件(读者插队)。这样的⽅式下,会导致写进程可能长时间等待, 且存在写进程“饿死”的情况。 为什么需要设置互斥信号量mutex,⽤于保护更新count变量时的互斥呢? 分析如下: 如果没有设置互斥信号量mutex,那么可能存在多个读者进程同时访问count变量,这样的话,可能 导致多次P(rw);操作⽽使得写进程长时间⽆法访问⽂件,并且此时的count计数变量的值可能也会不 准确。

写者优先算法

算法描述如下
1、只要有⼀个写者申请写数据,则不再允许新的读者进⼊读数据
2、写者会插队

故问题完整解答如下:
设置⼀个计数变量readercount,⽤来记录当前的读者数量,初值为0;
设置⼀个计数变量writercount,⽤于控制rsem信号量,初值为0;
设置互斥信号量rmutex,⽤于保护更新readercount变量时的互斥,初值为1;
设置互斥信号量wmutex,⽤于控制对writercount的互斥加减操作,初值为1;
设置互斥信号量rw⽤于保证读者和写者的互斥访问,初值为1。
设置互斥信号量rsem,当⾄少有⼀个写者申请写数据时互斥新的读者进⼊读数据,初值为1。

解决该问题的代码如下:

int readercount = 0;            //⽤用于记录当前的读者数量量 
int writercount = 0;            //⽤用于控制rsem信号量量 

semaphore rmutex = 1;           //⽤用于保护更更新readercount变量量时的互斥 semaphore wmutex = 1;           //⽤用于保护更更新writercount变量量时的互斥
semaphore rw = 1;               //⽤用于保证读者和写者互斥地访问⽂文件 
semaphore rsem = 1;             //当⾄至少有⼀一个写者申请写数据时互斥新的读者进⼊入读数据

writer() {
   while (1) {
   	 P(wmutex);
   	 if (writercount == 0) {            
   	 	P(rsem);        
   	 }       
   	 writercount++;        
   	 V(wmutex);        
   	 P(rw);        
   	 writing;        
   	 V(rw);        
   	 P(wmutex);        
   	 writercount--;        
   	 if (writercount == 0) {            
   	 	V(rsem);       
   	  }        
   	  V(wmutex);    
    } 
}
   
reader() {   
    while (1) { 
   	 P(rsem);        
   	 P(rmutex);        
   	 if (readercount == 0) {            
   	 	P(rw);       
   	  }        
   	  readercount++;       
   	  V(rmutex);        
   	  V(rsem);        
   	  reading;        
   	  P(rmutex);        
   	  readercount--;       
   	  if (readercount == 0) {           
   	   	 V(rw);        
   	   	}         
   	   	V(rmutex);   
    }
}

读写公平算法

读写公平算法即当有读进程正在读共享⽂件时,有写进程请求访问,这时应禁⽌后续读进程的请求,等待到已在共 享⽂件的读进程执⾏完毕则⽴即让写进程执⾏。同时读写公平算法也要遵循”先来后到“的准则,当⼀个写进程访问 ⽂件时,如果先有⼀些读进程要求访问⽂件, ⽽再有另⼀个写讲程要求访问⽂件,那么当当前访问⽂件的进程结 束对⽂件的写操作时,会是个读进程占⽤⽂件⽽不是写进程(在信号量w的阻塞队列上,因为读进程先来,⽽排在 阻塞队列队⾸,⽽V操作唤醒进程时唤醒的是队⾸进程)。

故问题完整解答如下:
设置⼀个计数变量count,⽤来记录当前的读者数量,初值为0;
设置互斥信号量mutex,⽤于保护更新count变量时的互斥,初值为1;
设置互斥信号量rw⽤于保证读者和写者的互斥访问,初值为1;
设置信号量w以实现读者写者之间的读写公平,初值为1。

代码如下:

int count = 0;                  //⽤用于记录当前的读者数量量 

semaphore mutex = 1;            //⽤用于保护更更新count变量量时的互斥
semaphore rw = 1;               //⽤用于保证读者和写者互斥地访问⽂文件 
semaphore w = 1;                //⽤用于实现读者写者之间的读写公平 

writer () {                     //写者进程 
   while (1) {        
   	P(w);                           
   	P(rw);                  //互斥访问共享⽂文件        
   	Writing;                //写⼊入        
   	V(rw);                 //释放共享⽂文件        
   	V(w);   
    }
}

reader () {         // 读者进程
   	while (1) {        
   		P(w);        
   		P(mutex);               //互斥访问count变量量       
   	 	if (count == 0) {       //当第⼀一个读进程读共享⽂文件时            
    			P(rw);              //阻⽌止写进程写       
   		 }                             
     	count++;                //读者计数器器加1        
     	V(mutex);               //释放互斥变量量count        
     	V(w);        
     	reading;                //读取        
      	P(mutex);               //互斥访问count变量量       
        count--;                //读者计数器器减1        
        if (count == 0) {       //当最后⼀一个读进程读完共享⽂文件            
      		 V(rw);              //允许写进程写        
        }            
        V(mutex);               //释放互斥变量量count  
    }
}

  • 25
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 经典问题是并发编程中的经典同步问题之一。它是指多个者和者同时访问共享资源时可能引发的问题。在此问题中,者可以同时取共享资源,但者只能在没有其他者或者正在访问共享资源时进行入操作。 通过采用"平等"的策略,我们可以使用信号量和PV操作来实现对的同步。具体实现步骤如下: 1. 定义两个全局变量:一个表示者个数的整型变量readcount,一个用于互斥访问共享资源的信号量mutex。 2. 操作实现如下: - 首先使用PV操作对mutex信号量进行P操作,即申请对共享资源的访问权限。 - 接着将readcount加1,表示有者正在取资源。 - 如果readcount为1,即当前者是第一个者,使用PV操作对者优先信号量reader_sem进行P操作,使得者无法进行操作。 - 释放对mutex信号量的P操作,使其他者可以同时进行操作。 - 取共享资源的操作。 - 使用PV操作对mutex信号量进行V操作,表示取资源完成。 - 如果readcount减到0,即当前者是最后一个者,使用PV操作对reader_sem进行V操作,使得者可以进行操作。 3. 操作实现如下: - 首先使用PV操作对reader_sem进行P操作,即申请对共享资源的访问权限,如果有者正在取资源,则无法进行操作。 - 进行操作,修改共享资源。 - 使用PV操作对reader_sem进行V操作,表示操作完成。 通过上述的实现策略,我们可以实现对的同步。在实际应用中,我们可以根据具体的需求和条件对操作进行合理的调度和控制,以保证共享资源的一致性和正确性。同时,需要注意在操作过程中对信号量的正确使用,避免出现死锁或竞态条件的情况。 ### 回答2: 通过研究经典的进程同步问题,我们可以采用"平等"的策略来实现对操作的信号量和PV操作。 在这个策略中,我们使用两个信号量,一个是readcount,用来记录当前正在的进程数目;另一个是mutex,用来实现对readcount的互斥访问。同时,我们使用PV操作来实现信号量的加减操作。 具体实现步骤如下: 1. 首先初始化readcount为0,mutex为1。 2. 当一个进程需要进行操作时,首先执行PV操作P(mutex)来申请对mutex的访问。 3. 然后执行PV操作P(readcount),将readcount加1。 4. 如果此时readcount为1,表示是第一个进程,则执行PV操作P(resource),来保护被取的资源,避免进程的干扰。 5. 然后执行PV操作V(readcount),将readcount减1。 6. 如果此时readcount为0,表示当前没有进程,可以释放对resource的保护,执行PV操作V(resource)。 7. 最后执行PV操作V(mutex),释放对mutex的访问。 通过以上步骤,我们可以实现对操作的同步,保证同一时间只能有一个进程进行操作,多个进程可以同时进行操作。这样可以确保数据的一致性和完整性。 总的来说,经典的进程同步问题可以通过使用信号量和PV操作,采用"平等"的策略来解决对操作的同步问题。这种方法可以有效地保证多个进程和一个进程之间的协调和管理,确保数据的正确性和并发性。 ### 回答3: 经典的进城同步问题指的是多线程环境下的一种资源竞争问题,即多个进程对某一共享资源的争夺。采用"平等"的策略,意味着者和者在竞争共享资源时享有相同的权利。 为了实现对操作的控制,可以使用信号量和pv操作。 首先,使用两个信号量来控制的访问。一个信号量read_count表示正在取的进程数量,另一个信号量write_count表示正在入的进程数量。初始时,read_count和write_count都为0。 当一个进程进入时,首先执行P操作,对read_count进行加1操作,表示有一个进程正在取。然后判断如果是第一个进程,执行P操作,对write_count进行加1操作,表示有一个进程正在入。接着执行V操作,对read_count进行加1操作,表示进程取结束。最后,如果是最后一个进程,执行V操作,对write_count进行减1操作,表示进程可以开始入。 当一个进程进入时,首先执行P操作,对write_count进行加1操作,表示有一个进程正在入。然后判断如果read_count不为0,说明有进程正在取,执行P操作,对write_count进行减1操作,表示进程需要等待。最后,进程进行操作,然后执行V操作,对write_count进行减1操作,表示进程入结束。 通过以上的策略和信号量PV操作,实现了对操作的控制。进程之间可以并行执行,进程需要等到所有进程结束后才能执行,确保了共享资源的一致性和完整性。这种实现方式可以避免冲突,保证了数据的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进阶媛小吴

规则简单易懂,粗暴却完美!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值