操作系统——两个同步互斥问题的详细推导

操作系统——两个同步互斥问题的详细推导

1.前置知识

信号量 : 信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。

进程的互斥:是指当有若干个进程都要使用某一共享资源时,任何时刻最多只允许一个进程去使用该资源,其他要使用它的进程必须等待,直到该资源的占用着释放了该资源。

最基本的场景就是:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。

进程的同步:是指在并发进程之间存在这一种制约关系,一个进程依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。

最基本的场景就是:两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。比如 A 任务的运行依赖于 B 任务产生的数据。

pv操作又称wait,signal原语。
主要是操作进程中对进程控制的信息量的加减控制。

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

可以将wait()理解为红灯,暂时无法通行,满足一定条件才能通行。
signal()理解为绿灯,让原本有红灯的位置可以通行。

2.司机与售票员问题

2.1问题背景

司机开车,售票员售票。

当售票员将门关上的时候司机才可以开车,

当司机将车到站停下的时候,售票员才可以打开车门。

首先写出代码块。

司机进程:
while(1){
    
   //S1:观察路况

   //S2:启动车辆
   
   //S3:正常驾驶
   
   //S4:到站停车

}
售票员进程:
while(1){
    
  //S5:关车门

  //S6:售票

  //S7:开车门
}
2.2分析关系

分析这两个进程的关系,显然,两个进程中的代码块存在先后关系,所以是同步问题

2.3确定信号量

启动车辆前要确保门是关着的(S7),开门前要确保车是停止的(S4),因此添加两个信号量close和stop,用来表示已经关门已经停止。close初始化为0,表示车门未关闭,stop初始化为0,表示车未停稳

2.4添加代码

先从司机进程看起。

S1:观察路况,司机什么时候都可以观察路况,不受条件限制,因此前后都不需要添加代码。

S2:启动车辆,司机在开车前显然要确保车辆的门是关着的,所以要在S2前面添加wait(close),只有当close为1时,也就是车关门时才会启动车辆,否则等待。

S3:正常行驶前后也不需要添加。

S4:到站停车后,要释放stop,在S7添加signal(stop),表示车已经停止,可以开门。

司机进程:
while(1){
    
   //S1:观察路况
   wait(close);
   //S2:启动车辆
   
   //S3:正常驾驶
   
   //S4:到站停车
   signal(stop);
}

售票员进程

S5:关门前没有限制,不需要添加代码,关门后要添加signal(close),表示车门已关闭,这样车才能启动。

S6:前后没有限制。

S7:开车么前,要确保车是停止的。因此要在前面添加wait(stop),表示车已经停止才能继续,否则等待。

售票员进程:
while(1){
    
  //S5:关车门
  signal(close);
  //S6:售票
  wait(stop);
  //S7:开车门
    
}

3.生产者消费者问题

3.1问题背景

缓冲区大小为N,假设有多个生产者和消费者,且只能有一个同时访问临界区

void producer()
{
    while(1)
	{
		//生产
	}
}

void consumer()
{
    while(1)
	{
		//消费
	}
}
3.2分析关系

生产者和消费者要共享缓冲区,不能同时使用缓冲区;因为有多个生产者和消费者生产者和生产者,消费者和消费者也不能同时使用缓冲区,因此是互斥关系

生产者与消费者,也有同步关系,消费者只有在缓冲区里有数据时,也就是生产者生产后,才能消费

而消费者在缓冲区满后,无法继续生成,只有在消费者消费后,才能继续生产。

3.3确定信号量

添加信号量mutex ,初始化为1。用于互斥访问临界区

full, 初始化为 0,表示缓冲区内数据数量,用来阻塞消费者,即只有有数据是才能消费。

empty ,初始化为 N,表示缓冲区的空位置的数量,用来阻塞生产者,即只有有空位置时,才能生成。

3.4添加代码

先分析同生产者在生产前要确保有空位置,即empty>0,否则等待,如果大于0,则会执行后面的语句,同时empty会-1(因为生产后空位减少了)。所以要在生产前添加wait(empty)

生产后要让full+1,表示缓冲区的数据增加1,因此要添加signal(full)

消费者在消费前要确保缓冲区内有数据,即full>0,否则等待,如果大于0,则会执行后面的语句,同时full会+1(因为消费后数据减少了)。所以要在消费前增加wait(full)。

消费后要让empty+1,表示缓冲区的空位增加1,因此要添加signal(empty)

void producer()
{
    while(1)
	{
        wait(empty);
		//生产
        signal(full)}
}

void consumer()
{
    while(1)
	{
        wait(full);
		//消费
        signal(empty);  
	}
}

再分析互斥

因为生产和消费不能同时进行,同时不同的生产者和不同的消费者也不能同时进行,因此可以使用共同的信号量mutex,在生产和消费前增加wait(mutex),只有mutex等于1时才会执行后面的操作,否则等待,在一个进程执行时,会将mutex-1,此时mutex等于0,其他进程就无法访问了,进程结束后,要signal(mutex),让mutex+1,才能执行其他进程。

mutex和empty、full的位置要怎么考虑呢?

因为两个进程等待是有前提的,比如生产进程只有在缓冲区有空位时才会和消费者进行互斥,消费者也是这样,所以放在同步的里面。

void producer()
{
    while(1)
	{
        wait(empty);
        wait(mutex);
		//生产
        signal(mutex);
        signal(full);
	}
}

void consumer()
{
    while(1)
	{
        wait(full);
        wait(mutex);
		//消费
        signal(mutex);
        signal(empty);  
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

捕赤鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值