前言
并发地访问公共资源而不加以控制,就会出现问题。如何在并发的条件下正确地访问共享资源一直是一大难题。
在数据库理论中,已经有了问题的答案:通过一系列的锁的机制,对独写的数据进行保护。可以看我之前的笔记:并发控制与冲突可串行化调度
但是对于操作系统来说,有一套更加朴实的机制来高效地处理公共资源并发访问问题,因为不同的环境需要不同的机制!并非一套模板就可以解决。
传统锁机制的缺点
在数据库理论中,通过上锁来避免对数据的同时访问。当你拿不到锁,那么就阻塞在原地,等其他人释放资源锁。
拿不到就嗯(广 c 话:硬)等的锁称为 “自旋” 锁,大概是因为程序会像盗梦空间里面的陀螺一样不断 while(1) 所以叫做自旋?
不断地 while(1) 并且询问锁是否被释放,对系统的开销是非常大的,因为即使被阻塞,进程还是占有 cpu,并且执行大量无意义的询问:“👴要的锁释放了吗?”
想象你在打开一个视频,视频加载的时候电脑什么也动不了,不能滑下去看评论,也不能点开作者的订阅空间… 反正我会骂一句猪 B,然后抡起圣毅之锤敲碎操作系统程序员的头盖骨。
在数据库中,嗯等没有大问题,因为从逻辑上来说你必须等。但是在操作系统中,你批事不干,就不能霸着 cpu,否则相当于强行将执行流导为串行。
于是便引入新的并行保护机制 ---- 信号量
信号量
如果你去拉屎,茅坑却被占了!
你不能一直在门口问:“兄弟你拉完没有?”
你应该告诉里面的兄弟:“你完事了喊一声,到我进去”
---- 这就是信号量。
好吧,我不太喜欢屎尿屁比喻,但是一时又找不到更好的。
信号量(semaphore)是一种特殊的调度变量,由一个 初始值为 1 的 整数 mutex,和一个任务队列 queue 组成,并且提供两个原子操作,wait 和 signal,用于管理。
wait 操作
先来看 wait 操作,也称为 P 操作。首先将 mutex 减一,如果 m u t e x ≥ 0 mutex \ge 0 mutex≥0 说明没有人和我们抢,那么执行当前任务。如果 m u t e x < 0 mutex<0 mutex<