互斥的几种实现方式:
一,忙等待互斥
1,禁止中断
2,锁变量
3,严格的轮换
4,peterson算法
5,Tsl
忙等待存在着各种各样的问题,一个最大的问题使消耗cpu,另外容器产生各种错误。而且还可能出现优先级反转问题,所以忙等待并不是很好的办法
互斥2-生产者消费者(原始状态)
一,休眠与唤醒
1,经典的生产者与消费者问题
生产者消费者现象的原型是这样的:
一个生产者生产,当缓冲区满了,就自己休眠
一个消费者消费,当缓冲区空了,就自己休眠
一个生产者生产,当生产一个产品时,就唤醒消费者(可以消费了)
一个消费者消费,当消费一个产品时,就唤醒生产者(可以生产了)
无论是生产者,还是消费着,当被唤醒的时候不一定马上执行,还需要获得cpu
◎这种设计产生了一个问题,原因是需要一个count来记录产品个数,而count的获得并没有互斥
例如如下情况:
消费者取得count=0,但是还没来得及休眠自己的时候,发生了系统进程调度,切换到生产者
生产者生产了一个产品后,唤醒消费者,但是这个时候的消费者并没有休眠,所以唤醒丢失
然后生产者继续生产,直到缓冲满了,自动休眠。
但是这个时候的消费者也是休眠状态,没有人来唤醒他,所以两个都一直休眠下去。
解决方案:
提供一个标志位,当生产者发送唤醒给消费者的时候,记录下来为1,当消费者要休眠之前检查一下这个标志位,如果是1就不休眠,如果不是就休眠
这个方法暂时解决了问题,考虑一下。
如果是m个生产者,n个消费者,m,n又很大的情况下,标志位就太多了。
这种情况下情况下地解决办法见下一篇文章 <互斥3-生产者消费者>
这个方案地实现程序如下:
#define N=100
int count=0;
void product(void){
int item;
while(TRUE){
item=produce_item()
if(count==N)sleep();
insert_item(item);
count=count+1;
if (count==1)wakeup(consumer);
}
}
void consumer(void){
int item;
while(TRUE){
if(count==0)sleep();
item=remove_item();
count=count-1;
if(count==N-1)wakeup(product);
consume_item(item);
}
}