详解C语言进程同步机制

2020-06-17 19:22:43王振洲

​在记录型型号量中,S->value的初值表示系统中某类资源的数目;对它每次wait操作,意味进程请求一个单位的该类资源,使得系统中可分配的该类资源数减少一个,因此描述为S->value–;当S.value<0时,表示在执行此次分配之前,系统中的该类资源已经全部分配完了,因此该访问进程应调用block原语进行自我阻塞,放弃处理机并插入到等待进程的队列S->list中。我们再来分析下signal操作,首先释放一个单位资源(S->value++),然后判断是否有进程在等待申请信号量,如果有的话,就应该调用wakeup原语从等待队列(list所链接的进程队列)中唤醒一个进程。

​通过上面的描述,我们来说一下在记录型型号量中,value值所代表的意义:1.value>0,此时表示系统中还剩余的该类资源的数量;2.value=0,此时恰好处于一个平衡状态,系统中的资源分配完了,同样也没有进程在等待资源,即list队列中是没有等待进程的;3.value<0,此时,value的绝对值表示有多少个进程在等待申请信号量,也即是list队列的长度。并且P、V操作必须成对的出现,有一个P操作就必定有一个与之配对的V操作(当为互斥操作时,它们同处于同一进程当为同步操作时,则不在同一进程中出现)。

4.3 AND型信号量

AND型号量正如其名,其基本思想是:将进程在整个运行过程中需要的所有资源,一次性的全部分配给进程,待进程使用完后再一起释放。AND型号量可以满足某些进程需要申请多个资源后才可以执行任务的场景,并且AND型信号量可以解决死锁问题,比如哲学家进餐问题中,一次给哲学家分配左右两支筷子,那么就不会有哲学家会因为吃不到空心粉而饿死了。

​AND型信号量使用的还是记录型信号量的数据结构,下面是Swait操作和Ssignal操作(此处和下面的信号量集都用此符号):

//记录型信号量定义
...

//P操作
Swait(S1, S2, ..., Sn){
 while(true){
  if(S1>=1&&...&&Sn>=1){
   for(i=1;i<n;i++) Si--;
   break;
  } else {
   将进程插入到第一个无法满足条件(即Si<1)的信号量对应的等待队列中,并且将程序计数器放置到
    Swait操作的开始处;
  }
	}
}

//V操作
Ssignal(S1, S2, ..., Sn){
 while(true){
  for(i=1;i<n;i++) {
   Si++;
   将Si中的等待队列中的所有进程全部移除,插入到就绪队列中;
  }
  break;
 }
}

​需要注意的就是,因为一次申请多个资源,所以在申请的过程中,如果因为哪一类资源不足而阻塞(请求N多个资源时第一个发现不满足的资源,即资源数<1),就要将进程插入到对应信号量的list中;与之对应的唤醒操作也有所不同,不再是唤醒阻塞队列中的某一个进程,而是将等待队列中的所有进程全部移除,插入到就绪队列中,让这些进程再次执行一次资源请求操作(这里因为是一次请求多个资源,后面可能依旧有资源无法满足进程的需求)。