计算机操作系统经典进程同步问题

1 )生产者—消费者问题(合作互斥)

是相互合作的进程关系的一种抽象,同时也包含着进程的互斥。

分析 :

  • 空缓冲区不为空,生产者才能将生产的数据放入缓冲区中。
  • 满缓冲区不为空,消费者才能从缓冲区中取数据。
  • 为了保证进程同步,生产者与消费者不可以同时访问缓冲区。

1)利用记录型信号量解决

in ;out;//生产者消费者指针
mutex//缓冲池互斥信号量
empty//缓冲池空缓冲区数量
full//缓冲池满缓冲区数量
/*buffer数组是用来表示缓冲区的,而empty和full是用来表示缓冲区
的空闲和使用情况的*/
//生产者
int in=0, out=0;
item buffer[n];
semaphore mutex=1, empty=n, full=0;
void proceducer() {
	do {
		producer an item nextp;//生产者生产的产品放入nextp中
		...
		wait(empty);//查看有无空闲的缓冲区
		wait(mutex);//使进程互斥
		buffer[in] =nextp;//把nextp中的产品送往buffer(in)
		in :=(in+l) % n;//指针偏移
		signal(mutex);//释放资源
		signal(full);//满缓冲区加1
	   }while(TRUE);
}
//消费者
void consumer() {
do {
	wait(full);//查看缓冲区是否有数据
	wait(mutex);//进程互斥
	nextc= buffer[out];//从buffer(out)中取出产品放入nextc
	out =(out+l) % n;//指针偏移
	signal(mutex);//释放资源
	signal(empty);//空缓冲区加1
	consumer the item in nextc;//消费nextp中产品
	}while(TRUE);
}

void main() {
	cobegin
	proceducer(); consumer();
	coend
}

注意 :

  • 互斥的wait(mutex)和signal(mutex)必须成对地出现;
  • 对资源信号量empty和full的wait和signal操作,同样需要成对地出现,但它们分别处于不同的程序中。
  • 每个程序中的多个wait操作顺序不能颠倒。应先执行对资源信号量的wait操作,然后再执行对互斥信号量的wait操作,否则可能引起进程死锁。

2)利用AND型信号量解决

即同时实现wait(empty)与wait(mutex)操作,与实现signal(mutex)与signal(full)操作。

  • Swait(empty, mutex) 代替 wait(empty)和 wait(mutex);
  • Ssignal(mutex, full) 代替 signal(mutex)和 signal(full);
  • Swait(full, mutex) 代替 wait(full)和 wait(mutex)
  • Ssignal(mutex, empty) 代替Signal(mutex)和Signal(empty)

代码如下 :

int in=0, out=0;
item buffer[n];
semaphore mutex=1, empty=n, full=0;
void proceducer() {
	do {
		producer an item nextp;
		Swait(empty, mutex);
		buffer[in] =nextp;
		in :=(in+1) % n;
		Ssignal(mutex, full);
	}while(TRUE);
}



void consumer() {
	do {
		Swait(full, mutex);
		nextc= buffer[out];
		out =(out+l) % n;
		Ssignal(mutex, empty);
		consumer the item in nextc;
	}while(TRUE);
}

2)哲学家进餐问题(资源耗尽,避免死锁)

临界资源的使用,避免死锁状况的产生。

解决方法 :

  • 记录型信号量:至多只允许有四位哲学家同时去拿左边的筷子, 最终能保证至少有一位哲学家能够进餐,并在用毕时能释放出他用过的两只筷子, 从而使更多的哲学家能够进餐。

  • AND型信号量: 仅当哲学家的左、 右两只筷子均可用时,才允许他拿起筷子进餐。

  • 数学方法:规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子;而偶数号哲学家则相反。按此规定,将是1、 2号哲学家竞争1号筷子; 3、 4号哲学家竞争3号筷子。即五位哲学家都先竞争奇数号筷子, 获得后, 再去竞争偶数号筷子, 最后总会有一位哲学家能获得两只筷子而进餐。

1)利用记录型信号量解决

//以第i位哲学家举例
semaphore chopstick[5]={ 1, 1, 1, 1, 1};
do {
	wait(chopstick[i]);
	wait(chopstick[(i+1)%5]);
	//eat
	signal(chopstick[i]);
	signal(chopstick[(i+l)%5]);
	//think
}while[TRUE];

2)利用AND型信号量解决

semaphore chopstick chopstick[5]={ 1, 1, 1, 1, 1);
do {
	...
	//think
	Sswait(chopstick[(i+1)%5], chopstick[i]);
	//eat
	Ssignal(chopstick[(i+1)%5], chopstick[i]);
}while[TRUE];

3)读者—写者问题(互斥问题)

互斥进程的管理 :

分析 :

  • 允许多个读者同时执行读操作
  • 不允许读者、写者同时操作
  • 不允许多个写者同时操作

1)记录型信号量解决 (写者优先)

读进程只要看到有其他读进程正在访问文件,就可以继续作读访问;写进程必须等待所有读进程都不访问时才能写文件,即使写进程可能比一些读进程更早提出申请。所以以上解法实际是 读者优先 的解法。

wmutex//读写互斥
readcount//读进程数目
rmutex//读进程计数

semaphore rmutex= 1, wmutex= 1;
int readcount=0;

//读进程
void reader() {
	do {
		wait(rmutex);//申请读,对读数更改
		if (readcount==0) wait(wmutex);/*第一个进入进行检验,防止正
		在写的情况*/
		readcount++;
		signal(rmutex);//释放读
		...
		perform read operation;
		...
		wait(rmutex);//申请读,对读数更改
		readcount--;//读者数减1
		if (readcount==0) signal(wmutex);//最后一个离开,唤醒写进程
		signal(rmutex);//释放读
	}while(TRUE);
}
//写进程
void writer()
{
	do {
		wait(wmutex);//申请写互斥信号量
		perform write operation;
		signal(wmutex);//释放信号量
	}while(TRUE);
}

void main(){
	cobegin
		reader(); writer();
	coend
}

2)利用信号量集解决有限同时读

  • 允许RN个读者同时执行读操作
  • 不允许读者、写者同时操作
  • 不允许多个写者同时操作
int RN;
semaphore L=RN, mx=1;
void reader() 
{
do {
	Swait(L, 1, 1);//L,下限为1,需求量为1
	Swait(mx, 1, 0);/*互斥信号量,下限为1,需求为0,当有写时mx为0,
	读失败*/
	...
	perform read operation;
	...
	Ssignal(L, 1)//释放资源
	}while(TRUE);
}
void writer()
{
	do {
	Swait(mx, 1, 1; L, RN, 0);/*既无writer写(mx=1),也无
	reader读(L=RN),writer进入临界区写*/
	perform write operation;
	Ssignal(mx, 1);
	}while(TRUE);
}

3)读者—写者写操作优先:

每个读进程最开始都要申请一下S信号量,之后在真正做读操作前即让出(使得写进程可以随时申请到 S)。而只有第一个写进程需要申请 S,之后就一直占着不放了,直到所有写进程都完成后才让出。等于只要有写进程提出申请就禁止读进程排队,变相提高了写进程的优先级。

semaphore rmutex=1,wmutex= 1, S=1, w=1;
int Readcount=0, Writecount=0;

//读进程
void reader() {
	do {
     	wait(S);//对读进程加以限制
        wait(rmutex);//读计数
        if(Readcount=0)wait(wmutex);//在无读者的情况下检验是否在写
        Readcount++;//读者数加1
        signal(rmutex);//释放读计数
      	signal(S);//加以限制
      	...
		perform read operation;
		...
		wait(rmutex);
        Readcount--;
        if(Readcount=0)signal(wmutex);//最后一个;离开唤醒写进程
      	signal(rmutex)
	}while(TRUE);
}

void writer{
	  do {
	  wait(w);
      if(Writecount=0)wait(S);//此时新的读者无法再进入读
      Writecount++;
      siganl(w);
      wait(wmutex);//写进程被唤醒后进行写操作
      ...
      perform write operation;//此时一直占据着信号量S,写进程一旦进入则顺序执行
      ...
      signal(wmutex);
      wait(w);
      Writecount--;
      if(Writecount=0)signal(S);//当所有写进程完成才归还信号量,读者可以再次进入临界区
      siganl(w);
}while(TRUE);
}

4)读者—写者问题公平竞争

方法相同,读写排队,谁先到拿到S,谁先操作。

void reader() {
	do {
     	wait(S);//对读进程加以限制
        wait(rmutex);//读计数
        if(Readcount=0)wait(wmutex);//在无读者的情况下检验是否在写
        Readcount++;//读者数加1
        signal(rmutex);//释放读计数
      	signal(S);//加以限制
      	...
		perform read operation;
		...
		wait(rmutex);
        Readcount--;
        if(Readcount=0)signal(wmutex);//最后一个;离开唤醒写进程
      	signal(rmutex)
	}while(TRUE);
}
void writer(){
    while(1){
        wait(S);//读写同时排队,谁先来谁先用
        wait(wmutex);
        signal(S);
        ...
        perform write operation
        ...
        signal(wmutex);
    }
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

从今天起请叫我小张

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值