操作系统——进程同步

经典同步问题

生产者-消费者问题

二者共享一个有界缓冲区,生产者向其中生产产品,消费者从中取出产品。

此过程中设置两个同步信号量,empty表示空缓冲区数量,其初值为N,full表示满缓冲区数量,初值为0,此外还要设置一个互斥信号量mutex,初值为1,来保证多个生产者或者多个消费者互斥地访问缓冲池。

分析条件:

  1. 有产品的情况下才能消费,full变量来控制;
  2. 缓冲区数量有限,不能无限生产,用empty来控制
  3. 同类进程互斥访问,mutex实现
full = 0;
empty = 0;
mutex = 1;
Pruducer(){
    
    
	wait(empty);//申请空缓冲区,自动更新空缓冲区数量
	wait(mutex);//申请访问缓冲区权限

	singal(mutex);//释放访问缓冲区权限
	singal(full);//更新满缓冲区数量,增加一个满缓冲区
	
}
Consumer(){
    
    
	wait(full);//申请空缓冲区,自动更新空缓冲区数量
	wait(mutex);//申请访问缓冲区权限

	singal(mutex);//释放访问缓冲区权限
	singal(empty);//更新满缓冲区数量,增加一个k空缓冲区
}

注意:
执行顺序不可颠倒,必须先进行对资源信号量的P操作,然后才能进行互斥信号量的P操作,否则可能导致死锁。

读写者问题

分析条件:

  1. 任意多个读者可以同时读这个数据区
  2. 同时只能有一个写者可以写这个数据区
  3. 如果一个写者正在写这个数据区,禁止任何读者和写者访问该数据区。

需要考虑问题:读者优先,公平情况,写者优先

读者优先

读者优先也就是若有读者在读,新来读者可以立马读,而写者必须等待所有读者全部读完才能写

readCount = 0;
wmutex = 1;
rmutex = 1;
Reader(){
    
    
	wait(rmutex);//申请readCount的使用权
	if(readCount==0){
    
    
			wait(wmutex);//阻止写者写数据
		}
		readCount++;//更新读者数量
		singal(rmutex);//释放使用权
		wait(rmutex);//申请readCount的使用权
		readCount--;//更新读者数量
		if(readCount==0){
    
    
			singal(wmutex);//允许写者写数据
		}
		singal(rmutex);//释放使用权
	
}

Writer(){
    
    
	wait(wmutex);//申请readCount的使用权
	singal(wmutex);//释放使用权
	
}

哲学家进餐问题

分析条件:
五个哲学圆桌而围,每个人只有一根筷子,如何解决进餐问题。

我们规定大家逆时针围桌而坐,0号哲学家的左手筷子为0号筷子,右边边筷子是1号筷子,以此类推。

sm = 4;
fork[5]={
    
    1,1,1,1,1};//5筷子是否被用
philosopher(int i){
    
    
	
	wait(fork[i%5]);//拿起左手筷子
	wait(fork[(i+1)%5]);//拿起右手筷子
	singal(fork[i%5]);//放下左手筷子
	singal(fork[(i+1)%5]);//放下右手筷子
	
	
}

以上过程可能造成死锁

sm = 4;
fork[5]={
    
    1,1,1,1,1};//5筷子是否被用
philosopher(int i){
    
    
	wait(sm);
	wait(fork[i%5]);//拿起左手筷子
	wait(fork[(i+1)%5]);//拿起右手筷子
	singal(fork[i%5]);//放下左手筷子
	singal(fork[(i+1)%5]);//放下右手筷子
	singal(sm);
	
}

或者


fork[5]={
    
    1,1,1,1,1};//5筷子是否被用
philosopher(int i){
    
    
	if(i%2!=0){
    
    
		wait(fork[i%5]);//拿起左手筷子
		wait(fork[(i+1)%5]);//拿起右手筷子
		singal(fork[i%5]);//放下左手筷子
		singal(fork[(i+1)%5]);//放下右手筷子
	}
	else{
    
    
		wait(fork[(i+1)%5]);//拿起右手筷子
		wait(fork[i%5]);//拿起左手筷子
		
		singal(fork[(i+1)%5]);//放下右手筷子
		singal(fork[i%5]);//放下左手筷子
	}
	
}

管程机制

管程定义了一个数据结构和能为并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据,管程构成的三部分:

  1. 局部对于管程的贡献数据结构说明
  2. 操作这些数据结构的一组过程
  3. 对于局部与管程的数据设置初始值语句

猜你喜欢

转载自blog.csdn.net/david2000999/article/details/120809824