操作系统-进程的同步与信号量

  1. 在临界区共同修改信号量产生错误
    第一次执行:
    p1.register=empty; p1.register=p1.register-1; empty=p1.register; p2.register=empty; p2.register=p2.register-1; empty=p2.register;z 第二次执行可能由于多个进程并发,调度引发共享数据错误. p1.register=empty; p1.register=p1.register-1; p2.register=empty; p2.register=p2.register-1; empty=p1.register; empty=p2.register;
    此处的regist是寄存器,empty是代表可用空闲资源,为2时表示进程有两个资源可用,为-1时表示有一个进程睡眠,处在阻塞队列中。
    注意这里不能对empty直接操作,直接用empty操作,在硬件层面数据的的操作也会落实回寄存器中去
  2. 在写共享变量empty时,采用上锁的方式阻止其他进程野访问empty
    临界区(一次只允许一个进程进入执行的一段代码0)
    基本原则,互斥进入,有空让进,有限等待.
  3. 轮滑法
    while(turn!=0);进入死循环无限等待 while(turn!=1);
    临界区 临界区
    turn=1; turn=0;
    剩余区 剩余区
    <-- 但是不满足有空让进,完成后不能再次进入-->
    4.标记法
    flag[0]=true flag[1]=false;
    while(flag[1]); while(flag[0]=true);
    临界区 临界区
    flag[0]=false; flag[1]=false;
    问题是在执行第一条语句时,切换到另一个线程,双方都会陷入无限等待
    5.peterson算法
    采用非对称标记和值日法来避免进程切换时造成当前进程无限等待
    flag[0]=true flag[1]=false;
    turn=1; turn=0;
    while(flag[1]&&turn0); while(flag[0]=true&&turn0);
    临界区 临界区
    flag[0]=false; flag[1]=false;
    此算法三条原则全部满足,但是面对多进程会比较麻烦
    6.面包店算法
    每个进程获取数组中更大的序号,最小序号先执行,离开时序号置为0,
    choosing=true;nums[i]=max(nums[0],nums[1],nums[n-1])+1;
    choosing=false;
    for(int j=0;j<n;j++){
    while(choosing);while((nums[i]>nums[j])&&nums[i]!=0);
    nums[i]=0;
    <--choosing是为了再选取序列号时,其他进程要进入死循环等待
    7.关闭中断
    另一个进程只有在被调度时才能执行临界区代码,所以通过关闭时钟中断,阻止时间片减小,让进程不被切换.
    cli();
    临界区
    sti();
    但是面对多cpu多核情况时,需要同步所有cpu
    8.硬件原子指令保护法
    { boolean rv=x;
    x=true;
    return x;
    }
    while(x);
    临界区
    x=false;
    锁(信号量)的依赖会来源于硬件,是原子指令,保证数据的一致性。
    此时这个函数的代码段对于cpu只是一条机器指令.
    ** 在多cpu情况下,要锁住总线,**
posted @ 2023-02-12 15:23  初冬又十三  阅读(35)  评论(0)    收藏  举报