同步互斥机制1

1)进程的并发执行

a.进程的特征:

并发:进程的执行是间断性的;进程的相对执行速度是不可预测的

共享性:进程/线程之间的制约性

不确定性:进程执行的结果与其执行的相对速度有关,是不确定的

b.进程并发执行的问题:

两个进程的关键活动出现交叉

2)进程互斥

竞争条件:两个或多个进程在读写某些共享数据,而最后结果取决于进程运行的精确时序

进程互斥:由于各进程要求使用共享资源(变量、文件等),而这些资源的使用要排他性使用,

各进程之间竞争使用这些资源

临界资源:系统中某些资源一次只允许一个进程使用,称这样的资源称为临界资源或互斥资源或共享变量

临界区:各进程中对某个临界资源(共享变量)实施操作的程序片段

临界区(互斥区)的使用原则:没有进程在临界区,想进入临界区的进程可进入

不允许两个进程同时处于临界区中

临界区外运行的进程不得阻塞其他进程进入临界区

不得使进程无限期等待进入临界区

a.进程互斥的软件解决方案

忙等待(busy waiting):进程在得到临界区访问权之前,持续测试而不做其他事情

自旋锁Spin lock(多处理器)

优先级反转(倒置)

解法一:(当初值为false的P进程执行完while(free);后离开CPU,Q进程开始执行,当进入临界区后离开CPU

(时间片用完之类的),P进程继续往下执行,也进入临界区,不满足临界区的使用原则,是个错误的解法)

free:临界区空闲标志:true有进程在临界区,false无进程在临界区;初值:false

P:……                              Q:……

while(free);                      while(free); 

free = true;                       free = true;

临界区                               临界区

free = false                         free = false

启示:把while(free);free = true;这两句封装成lock()函数,做成原子操作,就是正确的解法

free = false;封装成一个unlock()函数,原语操作

解法二:(P进程等待进入临界区,但Q一直不想进入临界区,P也不能进临界区,也就是Q进程阻止了P进程进临界区,

不满足临界区的使用原则,是不正确的)

turn:谁进临界区的标志:true:P进临界区,false:Q进程进临界区;初值任意

P:                                         Q:

……                                         ……

while(not turn);                        while(turn);

临界区                                      临界区

turn = false;                               turn = true;

……                                            ……

解法三:(P进程执行pturn = ture;后,时间片用完,Q进程也想进临界区,执行qturn = ture;便一直循环在while(pturn);

Q的时间片用完后,P继续执行,也在不断循环while(qturn);【Alten you问题】,不满足临界区的使用原则)

pturn,qturn:初值为false

P进入临界区的条件:pturn ^ not qturn

Q进入临界区的条件:not pturn ^ qturn

P:                                            Q:

……                                          ……

pturn = true;                              qturn = true;

while(qturn);                               while(pturn);

临界区                                        临界区

pturn = false;                              qturn = false;

……                                             ……

解法四——DEKKER算法:

在解法3的基础上引入turn变量,由turn决定在两个进程都想进临界区是让谁进

P:                                                       Q:

…  …                                                    …  …

pturn = true;                                        qturn = true;

while(qturn){                                         while(pturn){

     if(turn == 2){                                          if(turn == 1){

    pturn = flase;                                            qturn = false;

    while(turn == 2);                                        while(turn == 1): //忙等待

   pturn = true;                                                 qturn = true;

    }  }                                                                 }  }

  临界区                                                         临界区

turn = 2;                                                          turn = 1;

pturn = false;                                                 qturn = false;

解法五——PETERSON算法(如果两个进程都想进临界区,先给turn赋值的先进临界区)

进程i:

……

enter_region(i);

临界区

leave_region(i);

……


#define FALSE 0

#define TRUE 1

#define N     2   //进程的个数

int turn;            //轮到谁?

  int interested[N];  //兴趣数组,初始值为FALSE

void enter_region(int process)  //  process = 0 or 1

{

    int other;  // 另外一个进程的进程号

    other = 1 - process;

    interested[process] = TRUE;

   turn =  process;  //  设置标志位

   while(turn == process && interested[other] == TRUE);

}


void leave_region(int process)

{

    interested[process] = FALSE;

}

b.进程互斥的硬件解法

解法一——中断屏蔽方法(“开关中断”指令):

执行“关中断”指令

l临界区操作

执行“开中断”指令


优缺点:

简单高效;代价高,限制CPU并发能力(临界区的大小);不适用于多处理器;适用于操作系统本身,不适于用户进程


解法二——“测试并加锁”指令:(把总线锁住,先读后写后,打开总线)

TSL 指令:TEST AND SET LOCK


enter_region:

  TSL REGISTER,LOCK         | 复制锁到寄存器并将锁置1

CMP REGISTER,#0               | 判断寄存器内容是否为零

JNE enter_region                    | 若不是零,跳转到enter_region

RET                                         | 返回调用者,进入了临界区


leave_region:

MOVE LOCK,#0                     | 在锁中置0

RET                                        | 返回调用者


解法三——“交换”指令:

XCHG指令:EXCHANGE(在一条指令结束的时候,把两个位置上的内容交换)

enter_region:

MOVE REGISTER,#1          | 给寄存器中置1

XCHG REGISTER,LOCK              | 交换寄存器与锁变量的内容

CMP REGISTER,#0    | 判断寄存器内容是否是零

JNE enter_region                      | 若不是零,跳转到enter_region

RET                                           | 返回调用者,进入了临界区


leave_region:

MOVE LOCK,#0                     | 在锁中置0

RET                                        | 返回调用者

3)进程的同步

指系统中系统多个进程中发生的事件存在某种时序关系,需要相互合作,共同完成一项任务


生产者/消费者问题(有界缓冲区问题)

问题描述:一个或多个生产者产生某种类型的数据放置在缓冲区中

有消费者从缓冲区中取数据,每次取一项

只能有一个生产者或消费者对缓冲区操作

#define N 100                                 void consumer(void)
int count = 0;                                {
                                                 int item;
void producer(void)                               while(TRUE){
 int item;                                         if(count == 0) sleep();
 while(TRUE)                                        item = remove_item();
 {                                                  count = count - 1;
  item = produce_item();                         if(count == N-1)
  if(count == N) sleep();                          wakeup(producer);
     insert_item(item);                               consume_item(item);
  count = count + 1;                               }
  if(count == 1)                           }
  wakeup(consumer);
 }
}

4)信号量及PV 操作

a.信号量:一个特殊的变量;用于进程间传递信息的一个整数值

定义:stuc semaphore

{

int count;

queueType queue;

}

信号量说明:semaphore s;

对信号量可以实施的操作:初始化,P,V

P、V操作为原语操作

P、V操作定义:

P(s)                                                                       V(s)

{                                                                                 {

s.count --;                                                                         s.count ++;

if(s.count < 0)                                                                     if(s.count <= 0) // 小于零说明原来的队列上有进程在等

{                                                                                             {

  该进程状态设置为阻塞态;                                                  唤醒相应等待队列s.queue中等待的一个进程;

将该进程插入相应的等待队列s.queue末尾;                          改变其状态为就绪态,并将其插入就绪队列;

重新调度;                                                                               }

 }                                                                                     }

}

b.用P、V操作解决进程间互斥问题

分析并发进程的关键活动(涉及到共享变量的语句、代码),划定临界区

设置信号量mutex,初值为1

在临界区前实施P(mutex)

在临界区之后实施V(mutex)

c.用信号量解决生产者/消费者问题

#define N 100   //  缓冲区个数

typedef int semaphore;   //  信号量是一种特殊的整数型数据

semaphore mutex = 1;    //  互斥信号量:控制对临界区的访问

semaphore empty = N;   //  空缓冲区的个数

semaphore full = 0;        //  满缓冲区的个数

void producer(void)                             void consumer(void)
{                                               {
 int item;                                      int item;
 while(TRUE)                                    while(TRUE){
 {   item = produce_item();                 P(&full);
  P(&empty);                                   P(&mutex);   //两个P操作的顺序一定不能改变
  P(&mutex);                                   item = remove_item();
  insert_item(item);                           V(&mutex);
  V(&mutex);                                   V(&empty);   //两个V操作顺序可以改变
  V(&full);                                    consume_item(item); //不要放在V操作之前,那样会扩大临界区的范围
 }                                               }
}                                               }

d.用信号量解决读者/写者问题

问题描述:多个进程共享一个数据区,这些进程分两组:

读者进程:只读数据区中的数据;写者进程:只往数据区写数据

满足条件:允许多个读者同时执行读操作;不允许多个写者同时操作;不允许读者、写者同时操作


第一类读者写者问题:读者优先

如果读者执行:无其他读者、写者,该读者可以读

若已有写者再等,但有其他读者正在读,则该读者也可以读

若有写者正在写,该读者必须等

如果写者执行:无其他读者、写者,该写者可以写

若有读者正在读,该写者等待

若有其他写者正在写,该写者等待

void reader(void)                                       
{
 while(TRUE)
 {
  P(mutex);
  rc = rc + 1;//rc也是临界资源,所以需要P、V操作
  if(rc == 1) P(W);//第一个读者
  V(mutex);
  读操作
  P(mutex);
  rc = rc - 1;
  if(rc == 0) V(w);//最后一个读者
  V(mutex) ;
  其他操作
 }
}

void writer(void)
{
 while(TRUE)
 {
  ……
  P(w) ;
  写操作
  V(w) ;
 }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值