————————————————————————————————————————————————
前言:
*忙等待(busy waiting):当1个进程想进入临界区时,先检测。若不允许进入,则进程不断检测,直到许可为止。 后果:①浪费CPU时间 ②可能引起优先级反转
*进程的5种基本状态:新建(new)、就绪(ready)、运行(running)、阻塞(blocked)、完成(done)————————————————————————————————————————————————
信号量
1)什么是信号量?
OS引入的实现同步和互斥的机制
访问信号量S(取值为整数)的两个原子操作:P、V操作
P、V操作是原子操作(atomic operation),或称原语(primitive)
— 原子操作:即操作不可分割,要么全做,要么全不做
信号量的使用: 必须置一次且只能置一次初值 、只能执行P、V操作,除此之外,不能用其他方式访问信号量
2)信号量的含义?
信号量 s 的值表示可用资源的数量
P(s):请求分配一个资源
----当资源数s <= 0时等待,直到s > 0;然后请求资源,s - -;
V(s):释放一个资源
----s + +;
3)信号量的实现原理?
2种实现方式:忙等待方式、阻塞方式
忙等待实现方式:
***忙等待实现方式***
//信号量类型定义
typedef struct{
int value; //信号量的值
int lock; //锁,初始值为0
}Semophore_t
/*
设置一个共享变量lock:
lock = 0 : 未上锁,可进入临界区
lock = 1 : 已上锁,不可进入临界区
*/
//P操作
void P(Semophore_t *ps)
{
for(;;){
while(TSL(&ps->lock)); //当lock值为0时,表示可进入临界区,然后执行TSL操作,将lock值置为1,实现ps操作的互斥
if(ps->value > 0){
ps->value--; //当资源数大于0时,可申请分配资源,信号量value减一
break; //请求资源成功,跳出循环
}
ps->lock = 0; //当请求资源未被满足时,继续循环,TSL实现互斥
}
ps->lock = 0; //P操作结束,将lock值赋为0,解锁,允许其他操作进入临界区
}
//V操作
void V(Semophore_t *ps)
{
while(TSL(&ps->lock)); //上锁,实现对ps操作的互斥
ps->value++; //释放资源,信号量值加一
ps->lock = 0; //V操作结束,将lock值赋为0,解锁,允许其他操作进入临界区
}
阻塞实现方式:
***阻塞实现方式***
**引入等待队列,当需要等待时,将进程链入该信号量的队列中**
typedef struct{
int value;
int lock;
SemaQueue *list; //等待该信号量的进程队列
}Semophore_t;
//P操作
void P(Semophore_t *ps){
while(TSL(&ps->lock)); //上锁,互斥
if(ps->value > 0){
ps->value --;
ps->lock = 0; //释放lock
}else{
将该进程加入ps->list;
阻塞该进程并设置ps->lock = 0;
}
}
//V操作
void V(Semophore_t *ps){
while(TSL(&ps->lock)); //上锁,互斥
if(ps->list == NULL){
ps->value ++; //当没有进程处于等待队列,则释放资源
}else{
从ps->list中移出一个进程P;
将进程P放入就绪队列中;
}
ps->lock = 0; //执行完V操作,释放lock
}