1. 进程合作
多个进程共同完成一个任务
每个进程有自己执行的一套方案,但不是每个程序都是可以随便执行的,有时候需要等待,有的进程会给它发一些信号,根据这些信号来决定是否继续执行
2. 生产者-消费者实例
那个地方需要停?那个地方需要走?
3. 只发信号还不能解决全部问题
问题的关键在于消费者仅仅是在缓冲区满的时候知道有生产者在等待
也就是sleep了两个进程,而wakeup的时候只能唤醒一个进程,p2永远不会唤醒
4. 从信号到信号量
信号量开始工作了
根据信号量的值就知道要干什么
sem = -1 说明有一个进程在等待
c执行一个,唤醒一个进程,sem+1
简单来说:当缓冲区满的时候,来了一个进程生产者p1,就等待,然后sem=-1,又来了一个生产者p2,也得等待,sem=-2,这个时候消费者执行1次,就唤醒一个生产者p1,sem+1,也就是sem=-1,又消费了一次,就又唤醒一个生产者p2,sem=0,此时,没有生产者等待,而又消费了一次,sem=1,说明当前有一个进程对应的资源可用,又来了一个进程生产者p3,就直接执行,sem=sem-1
sem=1,表示当前有一个资源可以使用,不用等待
信号量是负的,表示等待
例题:
一种资源的数量是8,也就是信号量的初值是8,当sem=0的时候就是没有资源可以使用,而当前的信号量是2,也就是现在可以有2个资源使用
5. 信号量实现
首先定义一个结构体,然后就是P对应的消费资源(判断是否该睡眠),V对应的生产资源(判断是否该唤醒)
当消费资源的时候,首先信号量减1,如果减1之后小于0,说明当前的信号量sem是小于或等0,也就是当前没有资源可用,此时要进入睡眠
当生产资源的时候,首先信号量加1,如果加1之后小于或等于0,说明当前的信号量最大是-1,也就是sem=-1,说明要唤醒一个进程
p():sem-1 , 如果sem<0,等待,否则继续
V():sem+1 ,如果sem<=0 , 唤醒一个等待的p
6. 用信号量解决问题
正确性要求:
- 在任何一个时间只能有一个线程操作缓冲区(互斥)
- 当缓冲区为空,消费者必须等待生产者(调度/同步约束)
- 当缓存区满,生产者必须等待消费者(调度/同步约束)
每一个约束用一个单独的信号量
- 二进制信号量互斥mutex
- 一般信号量full,一开始为空为0
- 一般信号量empty,一开始为缓存区满的数据