操作系统(8)进程--同步互斥介绍;同步问题的三种解决方案:禁用硬件中断、基于软件、更高级抽象

版权声明:版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/lililuni/article/details/83755732

1. 背景

同步互斥是操作系统协调进程之间动作和相互关系中的机制。互斥是指当一个进程在临界区访问共享资源时,其他进程不能进入该临界区访问任何共享资源。为实施互斥,进程之间就要采用同步机制。

  1. 并发进程的正确性
    ==1==
  2. 进程并发运行的好处

    共享资源
    加速:I/O操作和CPU计算可以重叠,程序可分为多个模块在多个处理器上并行执行
    模块化:将大程序分解成小程序,使系统易于复用和扩展。

  3. 原子性操作
    原子性操作时操作系统硬件提供的操作,它保证一些执行语句必须是原子操作。
    ==2==

2. 同步问题的一个例子

本节用一个简单的生活问题来理解同步。(具体分析过程详见视频:同步问题

  1. 下图中,如果A和B的按照图中的顺序执行的话,就会出现面包重复购买的情况
    ==3==
    首先来分析下这个问题:
    ==4==

  2. 解决方案
    利用两个原子操作来实现一个锁(lock)

    Lock.Acquire():在锁被释放之前一直等待,然后获得锁,如果两个进程都在等待同一个锁,并且同时发现锁被释放了,那么只有一个获得锁,另一个仍处于等待
    Lock.Release():解锁并唤醒任何等待中的进程

    ==5==

  3. 进程的交互关系
    ==6==


3. 同步问题的初步解决方案

==7==

临界区:进程中访问临界资源的一段需要互斥执行的代码(也就是说有一个进程在访问临界区代码,另一个进程就不能访问该代码)
进入区:检查可否进入临界区的一段代码,如可进入,则设置相应“正在访问临界区”标志‘
退出区:清楚“正在访问临界区标志”
剩余区:代码的其余部分
临界区访问规则
空闲则如:没有进程在临界区,则任何进程可以进入
忙则等待:有进程在临界区,其他进程均不能进入临界区
有限等待:等待进入临界区的进程不能无限制等待
让权等待(可选):不能进入临界区的进程,应释放CPU(比如转换到阻塞状态)

1. 方法一 禁用硬件中断

也就是禁止硬件中断的响应,相当于把中断使能关掉了。
==8==
==9==

2. 方法二 基于软件的同步办法

该方法就是通过进程共享一些共有变量来实现线程的同步。该方法的特征一是复杂(需要两个进程间的共享数据项),二是需要忙等待,浪费CPU时间。

  1. 示例
    ==10==

  2. Peterson算法
    ==14==

    第一种情况:另外一个进程Tj没有申请进入,则此时flag[j]为false,Ti可以正常进入临界区
    第二种情乱:Tj申请进入,flag[j]为true,则先写turn语句的会进入临界区。比如说是Ti先写turn=j,则此时Ti 进不去(while两个条件都满足,会一直循环),然后Tj写turn(turn=i)后,Ti就会立马进去了,Ti运行完临界区代码后,flag[i]=false,则Tj就可以进去了。

    ==16==

  3. Dekkers算法
    ==17==
    ==18==

3. 方法三 更高级的抽象方法

硬件提供了一些同步原语,比方说中断禁用、原子操作指令等,操作系统提供了更高级的编程抽象来简化进程的同步,比方说信号量(这两个都是用硬件原语来构建的)


  1. 锁是一个抽象的数据结构,它由一个二进制变量(锁定/解锁)和两个操作原语组成。它是基于原子操作指令来实现的

    Lock.Acquire():在锁被释放之前一直等待,然后获得锁,如果两个进程都在等待同一个锁,并且同时发现锁被释放了,那么只有一个获得锁,另一个仍处于等待
    Lock.Release():解锁并唤醒任何等待中的进程

  2. 原子操作指令
    CPU体系结构中提供了一些特殊的原子操作指令,这些指令把若干个操作合成一个原子操作,保证这些操作之间不会部分执行的状态。

    • TS指令
      ==19==
    • 交换指令(交换内存中的两个值)
      ==20==
  3. 使用TS指令实现自旋锁
    ==21==
    ==22==

  4. 原子操作指令锁的特征
    ==23==

  5. 同步方法总结
    ==24==

猜你喜欢

转载自blog.csdn.net/lililuni/article/details/83755732