进程的同步

  • Post author:
  • Post category:其他


解决多个进程同时访问同一个资源的时候出现数据破坏的问题

  1. 首先找到临界区

    临界区:一段代码对共享的数据进行访问
  2. 然后对临界区进行保护


    加锁


    应该满足三个条件:

    • 互斥
    • 进度
    • 有限等待

软件方法(现在不常用)

这里写图片描述

硬件方法(常用)

这里写图片描述

硬件方法有以上两种,下面仅介绍第一种,这种操作是基于硬件的原子指令(执行过程中不能被中断)实现的。TestAndSet()就是原子操作

这里写图片描述

这里写图片描述

临界区要设置的恰到好处,不能太小,防止数据保护不可靠;也不能太大,影响程序的并行执行(原因是当临界区太大的时候,会将一些不需要保护的内容也也起保护,那么当一个进程在访问临界区中的数据时,其他进程就不能够访问)。

信号量(semaphore)

是IPC(进程间通信)的一种策略,但也很好的解决了进程同步的问题

信号量的两种基本操作:

1. wait()操作

2. signal()操作

wait和signal是原子操作

这里写图片描述

这里写图片描述

信号量有一个特点就是可以控制进入临界区的线程数(counting semaphore),上图中mutex变量的数值就代表线程数。

从上述可以看出,当一个进程在等待临界区的时候,是一个死循环,所以为了解决这种情况,采用以下方法,改进信号量的定义:

这里写图片描述

struct process 指针将所有正在等待的进程串联起来,将其置于阻塞态,等临界区释放的时候,再将其置于就绪态。

以下为实现方法:

block();//将进程阻塞

wakeup();将进程唤醒

这里写图片描述

进程同步的问题:

这里写图片描述

各种问题的解决方法
  1. Producer-Consumer Pronblem(生产者消费者问题):

    生产者写数据,消费者取数据,生产者们或消费者们同时操作都会对数据产生影响。也就是说同一时刻只能有一个生产者和一个消费者进行操作。

    • N buffers, each can hold one item.
    • 这里写图片描述

      生产者的实现代码:

      wait(mutex)和signal(mutex)是为了保护缓存区只能有一个进程来写。wait(empty)执行时empty- -, 表示缓冲区少了一块,同时将可以写入的生产者的数量减少一个,empty初值表示系统提供empty个生产者可以写数据,但不是同时进行的; signal(full)执行时full++,表示缓冲区可用数据块多了一个,可以供消费者读取的线程多了一个。
    • 这里写图片描述

      消费者的实现代码:
    • 这里写图片描述
  2. readers and readers peoblems(读者写者问题):

    读者同时读不会对数据产生影响,写者会。也就是说同一时刻只能有一个写者可以对数据进行操作,而读者则无限制。

    • 信号量的定义

      这里写图片描述

    • 写者

      这里写图片描述

    • 读者

      读者每增加一个,readcount++;当第一个读者开始读时,执行wait(wrt),表示等待写者写完,然后拿过写者的权利来,只要有读者在读,写者就不能写入。也就是读的时候不能写,写的时候不能读。

      这里写图片描述

  3. dining-philosophers problems(哲学家就餐问题):

    这里写图片描述

    这里写图片描述

这里写图片描述


管程

管程时一种更高阶的对临界区进行保护的方法,实现于语言层面,而不是系统调用层面。


部分操作系统对实现进程同步的方法

  • Solaris

    • adaptive mutexes(自适应互斥锁)
先介绍两个概念

回旋锁:等待锁的时候(wait)不断循环判断

非回旋锁:等待锁的时候处于阻塞状态

自适应就是先回旋,如果一段时间后还等不到锁,那么就非回旋进入阻塞态;因为如果等待的时间很短,那么进入阻塞态等待的话就得不偿失了

  • Windows xp

    • 关中断 (单处理器)
    • 回旋锁 (多处理器)
  • Linux

    • 禁止内核抢占
    • 回旋锁
    • 信号量



版权声明:本文为haha_YM原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。