谈谈你理解的进程同步与互斥?

进程互斥、同步的概念是并发进程下存在的概念,有了并发进程,就产生了资源的竞争与协作,从而就要通过进程的互斥、同步、通信来解决资源的竞争与协作问题。

进程之间的同步与互斥问题,究竟是怎么一回事?

详细回答

同步和互斥的概念

  1. 同步:同步关系,在专业领域也被称作进程的直接相互制约关系,遵循“程序 — 程序模式”。它主要描述的是多个协作进程在执行任务过程中,彼此之间相互等待或者进行通信的协作关系。在实际的多进程系统中,这些协作进程为了完成一个共同的任务,需要按照一定的顺序和节奏进行操作。例如,一个进程可能需要等待另一个进程完成某个特定的操作后才能继续执行,或者进程之间需要交换数据来协调工作,这种相互依赖和协作的关系就是同步关系的体现。
  2. 互斥:互斥关系,也被叫做进程的间接相互制约关系,采用“程序 — 资源 — 程序模式”。当一个进程进入临界区访问临界资源时,其他进程必须等待。只有当访问临界资源的进程退出临界区后,其他进程才被允许访问该临界资源。这种机制体现的是进程之间的竞争关系,因为临界资源在同一时刻只能被一个进程访问,多个进程都希望获取该资源,从而产生了竞争。例如,多个进程同时访问共享的文件、打印机等资源时,就需要通过互斥机制来保证资源的正确使用,避免数据混乱和冲突。

如何实现进程同步和互斥

  1. 软件实现方法

    • ①单标志法:该方法通过设置一个共享的变量标志来控制进程对临界区的访问。通常使用一个整型变量turn,其取值可以为0或1,专门适用于两个进程的场景。当turn取值为0时,进程P0获得进入临界区的权限,在P0退出临界区时,它会将turn的值置为1,从而将进入临界区的权限转让给进程P1,进程P1的进入和退出过程同理。然而,这种方法存在明显的问题,它强制要求进程轮流进入临界区,这与实际的应用场景不符,因为在实际情况中,进程对临界区的访问需求可能是随机的,不一定需要轮流进行。此外,该方法违背了“空闲让进”准则,即当临界区空闲时,其他有需求的进程可能因为这种轮流机制而无法及时进入。
    • ②双标志先检查法:与单标志法相比,双标志先检查法将共享变量turn替换为数组flag[2]。进程在进入临界区之前,会先检查对方的标志位,例如使用while (flag[1]); 语句进行判断。但这种方法存在缺陷,它不能保证进程对临界资源的互斥使用。由于检查和进入临界区的操作不是原子的,可能会出现两个进程同时检查对方标志位,并且都认为对方没有进入临界区,从而导致两个进程同时进入临界区的情况,这违背了“忙则等待”准则,即当临界区正在被使用时,其他进程应该等待。
    • ③双标志后检查法:此方法先设置自己的标志,然后再进行准入检测。进程在进入临界区之后才检查对方的标志位。这种方式可能会导致两个进程均陷入无限等待的状态,即两个进程都无法跳出while循环。因为在某些情况下,两个进程可能同时设置自己的标志,然后又同时检查到对方的标志,从而都认为对方正在使用临界区,导致双方都无法进入临界区,这违背了“有限等待”和“空闲让进”准则。
    • ④Peterson算法:Peterson算法结合了单标志位和双标志后检查法的特点。它既设置了flag标志,用于表明进程是否希望进入临界区,又设置了共享变量turn,用于规定进程进入临界区的顺序。该算法满足互斥条件、空闲让进条件和有限等待条件,能够在一定程度上解决进程对临界区的互斥访问问题。然而,它也存在局限性,不满足“让权等待”准则,即当进程无法进入临界区时,它仍然会占用CPU资源进行忙等待。此外,Peterson算法只能处理两个进程之间的临界区问题,在实际的多进程系统中,往往需要处理多个进程的同步和互斥问题,因此该算法不符合实际需求。
  2. 硬件实现方法

    • ①关中断方法:在进入临界区之前,进程会执行关中断操作,暂停进程调度,使得该进程能够独占处理机。当进程完成对临界区的访问并退出临界区后,再执行开中断操作,恢复进程调度。关中断方法满足了“空闲让进”“忙则等待”和“有限等待”的准则。但是,这种方法存在明显的局限性,它不适用于多处理器环境。因为在多处理器系统中,不同的处理器可以同时执行不同的进程,关中断只能影响当前处理器,无法保证其他处理器上的进程不会访问临界资源。
    • ②硬件指令方法
      • TSL(Test and Set Lock):TSL指令通过硬件实现原子操作,它会测试一个标志位的值,并将其设置为特定的值。利用TSL指令可以实现对临界区的互斥访问,确保在同一时刻只有一个进程能够进入临界区。
      • Swap:又称exchange指令,该指令通过硬件实现两个变量值的交换。在同步和互斥的实现中,可以利用Swap指令来交换标志位的值,从而实现进程对临界区的互斥访问。
  3. 高级同步机制

    • ①信号量:信号量的基本原理是在多个进程之间使用简单的信号来实现同步。在操作系统中,信号量是一种与一类临界资源相关联的数据结构。信号量的不同取值表示一个临界资源的不同状态,例如,信号量的值为正数时,表示可用的临界资源数量;信号量的值为0时,表示临界资源正在被使用,没有可用资源;信号量的值为负数时,表示有进程正在等待该临界资源。信号量机制可以用于实现进程的同步和互斥,它支持P()和V()操作,P()操作通常用于申请资源,会使信号量的值减1;V()操作通常用于释放资源,会使信号量的值加1。
    • ②管程:管程是一个软件模块,它由一些公共变量以及描述和访问这些变量的函数组成。进程对共享资源的请求、释放和其他操作必须通过同一个管程来实现。当多个进程请求访问同一资源时,管程会根据资源的使用情况接受或拒绝这些请求,确保每次只有一个进程能够进入临界区,从而有效实现进程的互斥。管程的引入简化了进程同步和互斥的实现,提高了代码的可读性和可维护性。
    • ③屏障:屏障是一种用于同步多个进程或线程的机制,它的主要作用是确保多个进程或线程在某个特定的点之前不会继续执行。当进程或线程到达屏障时,它会进入等待状态,直到所有相关的进程或线程都到达屏障后,这些进程或线程才会继续执行。屏障机制非常适合需要多个进程或线程同步执行的场景,例如并行计算和多阶段任务。在并行计算中,多个线程需要在某个计算阶段完成后才能继续进行下一步操作,这时可以使用屏障来确保所有线程都完成了当前阶段的计算。
    • ④条件变量:条件变量是一种用于在多个进程或线程之间传递状态信息的同步机制。当进程或线程发现某个条件不满足时,它会进入等待状态;当条件满足时,它会被唤醒继续执行。条件变量通常与互斥锁一起使用,以避免竞争条件。互斥锁用于保证对共享资源的互斥访问,而条件变量用于在进程或线程之间传递状态信息,两者结合可以实现更复杂的同步和互斥需求。例如,在一个生产者 - 消费者模型中,消费者进程可能会在缓冲区为空时通过条件变量进入等待状态,当生产者进程向缓冲区中添加数据后,会通过条件变量唤醒等待的消费者进程。 —

知识拓展

在多进程系统中,进程之间同步与互斥机制的实现,需要严格遵循以下四条设计准则,以确保系统的高效性、稳定性以及资源的合理利用。

空闲让进

当某个进程向系统发起进入特定临界区的请求时,若此时该临界区内没有其他进程正在访问临界资源,系统应立即准许该进程进入临界区。这一准则的核心在于充分利用临界资源,避免资源的闲置浪费。通过及时响应进程的请求,使得临界资源能够在有需求时迅速被使用,从而提高系统整体的资源利用率和运行效率。例如,在一个共享文件的系统中,当文件没有被其他进程占用时,新的请求进程应能够立即获得访问权限,对文件进行读写操作。

忙则等待

若已有一个进程成功进入临界区,并正在对临界资源进行访问,那么其他期望进入该临界区的进程必须在临界区之外进行等待。这一准则是实现进程互斥访问临界资源的关键。因为临界资源往往具有排他性,同一时刻只能被一个进程使用,若多个进程同时访问,可能会导致数据不一致、资源损坏等问题。通过让其他进程在临界区外等待,确保了临界资源在任何时刻都只能被一个进程独占访问,保证了系统的正确性和稳定性。比如,在多个进程共享打印机的场景中,当一个进程正在使用打印机时,其他进程必须等待,直到该进程使用完毕。

有限等待

对于那些请求访问临界资源的进程,系统必须保证它们能够在有限的时间内进入对应的临界区。如果一个进程长时间无法获得所需的临界资源,处于“无限等待”的状态,即使最终它成功获得了临界资源,也可能会因为等待时间过长而导致其任务失去实际意义,影响系统的整体性能和响应速度。为了实现有限等待,系统可以采用合理的调度算法和资源分配策略,对进程的等待时间进行监控和管理,确保每个请求进程都能在可接受的时间范围内得到资源并继续执行。例如,在操作系统中,可以为每个进程设置一个最大等待时间,当超过这个时间仍未获得资源时,系统可以采取相应的措施,如调整资源分配优先级等。

让权等待

当一个进程由于某些原因无法进入临界区时,它应该立即释放处理器资源。这一准则的目的是提高处理器的利用率,避免出现“忙等”现象。在“忙等”情况下,进程虽然无法进入临界区,但仍然占用着处理器资源,不断进行无效的循环检查,这会导致处理器资源的浪费,降低系统的整体性能。通过让无法进入临界区的进程释放处理器,使得其他有需要的进程能够及时获得处理器资源并执行,从而提高了系统的并发处理能力和资源利用效率。例如,在一个多线程的程序中,当某个线程无法获取锁进入临界区时,它应该主动放弃CPU时间片,让其他线程有机会运行。