互斥锁
特性:
1.需要忙等,进程时间片用完才下处理机,违反让权等待
2.优点:等待奇迹不用切换进程上下文,多处理机系统中,若上锁的时间短,则等待的代价很低
3.常用于多处理机,一个核忙等,其他核照常工作,并快速释放临界区
4.不太适合用于单处理机系统,忙等过程中不可能解锁
信号量机制
用户可以使用操作系统提供的一对原语来对信号量进行操作,方便实现进程互斥,进程同步
信号量就是一个变了,可以用一个信号量来表示,系统中某种资源的数量,比如说系统中只有一台打印机,就可以设置一个初始值为1的信号量
原语是一种特殊的程序段,只能一气呵成不可被中断,原语是由开关中断指令实现的,软件方案主要问题是“进入区的各种操作无法一气呵成”,因此只要把进入区和推出区的操作都用原语实现,就能一气呵成
一对原语:wait(S)和signal(S),可以把原语理解诶我们自己写的函数,里面的S是传入的参数
wait和signal也被称为P/V操作来自荷兰语(proberen/Verhogen)
整型信号量
用一个整形的变量作为信号了,用来表示系统中的某种资源数量
比如说系统中有一台打印机
int S=1;void wait(int S){ //进入区while(S<=0); // 如果资源不够就一直循环等待S=S-1; // 如果资源够就占用一个资源
}void signal(int S){//退出区S=S+1 //用完资源后,在推出区释放资源
}
//process0:
...
wait(S);
//使用打印机的指令
signal(S);
...//process1
...
wait(S);
//使用打印机的指令
signal(S);
...
不满足让权等待,它会一直占用处理机进行while循环直到时间片用完
记录型信号量
整形信号量存在忙等的问题,因此人们提出了记录型信号量,即记录型数据结构表示的信号量
typedef struct{int value; //剩余的资源数量struct process *L; //等待队列
}semaphore;
void wait(semaphore S){S.value--;if (S.value<0){block(S.L);}
}void signal(semaphore S){s.value++;if (S.value<=0){wakeup(S.L);}
}
具体例子: https://www.bilibili.com/video/BV1YE411D7nH/?p=32&share_source=copy_web&vd_source=7b850f4882e6be926b6eb30758a00e34&t=995
当S.value<0的时候,进程会主动调用block原语进行自我阻塞,就不会出现忙等的情况,尊旭了“让权等待”
对信号量进行V操作,意味着释放一个单元的该资源,会执行S.value++
完成+1后,如果value依然小于0,那么就会调用wakeup原语,唤醒队列中的第一个进程,从阻塞态-》就绪态