17、信号量临界区保护

靠临界区保护信号量,靠信号量实现进程之间的同步

为什么要保护信号量

温故知新:什么是信号量

信号量就是资源的充裕度:通过对这个量的访问和修改,让多进程有序推进

注:信号量不是资源数量,因为信号量可以为-3,但是能说数量为-3吗?不能。信号量只能说代表充裕度,

​为正,表明资源充足,有n个资源
为负,表明资源匮乏,还少n个资源(有n个线程因资源匮乏而阻塞)

为什么要保护信号量

多线程请求资源时,程序需要根据 资源充裕度决定是否予以放行(是否堵塞)。
那么必要的前提:就是保证资源充裕度这个共享的变量一定要被正确的修改。

什么是临界区

临界区就是一次只允许一个进程进入的那段代码

使用什么方法保护信号量,从而实现临界区

注:信号量和临界区的关系:信号量的修改代码 就是临界区

临界区代码的保护原则

互斥进入
一个进程在临界区中执行,就不在允许其他进程进入临界区

有空让进
临界区空闲时,一定要允许其他的进程进入

有限等待
一个进程从发出进入临界区请求开始,到进入临界区,不能无限等待

整体思路在这里插入图片描述

在进入区和退出区分别写一些代码(临界区保护代码),保证临界区一次只能被一个进程访问

怎么保护信号量

整体思路

在这里插入图片描述
在这里插入图片描述

具体实现

Perterson算法

只能用于两个进程之间的同步
在这里插入图片描述
从已经声明要修改信号量的进程中选取一个进程的方法针对全局变量的退让机制

面包店算法

 // 变量说明:
 // i 表示当前进程PID
 // j 表示当前迭代到的进程PID
 // choosing[i] 表示当前进程i 是否正在 【声明修改信号量】, 默认值为false
 // number[i] 表示当前进程i的排队号, number[i] > 0:表示 【已经声明要修改信号量 】。默认值为0
 
 process(i) {
    
    
     while (true) {
    
    
         // 当前进程i正在 【声明修改信号量】
         choosing[i] = true;
         // number为上一个已发放的排队号加1
         number[i] = 1 + max(number[1], number[2], ..., number[n-1]);
         // 当前进程i 【声明修改信号量】 完毕
         choosing[i] = false;
         
         // 迭代所有进程
         for (j = 0; j < n; j++) {
    
    
             // 若当前迭代到的进程j正在【声明修改信号量】, 则等待其声明完毕
             while(choosing[j]);
 
             // 同时满足以下两个条件,一直空转:
             //      a、存在其他进程 【已经声明修改信号量 】
             //      b、选中的进程不是自己
             // number[j] != 0:存在其他进程j 【已经声明修改信号量 】
             // (number[j], j) < (number[i], i):选中幸运线程,规则:选中号码最小的 ,如果号码一样的,则选择 最先请求的
             while (number[j] != 0 && (number[j], j) < (number[i], i));
         }
 
         // 临界区代码
 
         // 当前线程【声明不再修改信号量】
         number[i] = 0;
     }     
 }

从已经声明要修改信号量的进程中选取一个进程的方法编号机制

Guess you like

Origin blog.csdn.net/qq_43579103/article/details/119678586