Posts Process Synchronization
Post
Cancel

Process Synchronization

进程同步

背景

协作进程 :与系统内的其它进程相互影响的进程

协作有两个方面的体现

  • 共享逻辑地址空间
  • 通过文件或消息来共享数据

共享逻辑地址空间可能会导致各种各样的问题,比如共享数据可能因为并发的访问而不同

假设有两个协作进程要访问修改共享地址中的Counter变量,CPU修改变量要经过三步

1
2
3
MOV ax,Counter
ADD ax,1
MOV Counter,ax

然而在系统中进程是并发执行的;这意味着P1进程可能还没执行完这三个步骤就被P2抢占执行了,这时Counter的值可能会跟我们预想的不一样

我们把异步环境下的一组并发进程因直接制约而互相发送消息、进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步;

进程同步的各种机制确保协作进程有序的执行

临界区问题

每个进程都有一段临界区,当一个进程进入临界区,没有其他进程可被允许在临界区内执行,即没有两个进程可同时在临界区执行

临界区的通用结构:

1
2
3
4
5
6
7
8
9
do{
    /* 进入区 */

    临界区

    /* 退出区 */

    剩余代码
}while(1)

临界区问题的解答要满足三个要求

  • 互斥
  • 前进 :如果没有进程在临界区执行,那么就要选择进程进入临界区执行

  • 有限等待 :从一个进程请求进入临界区的请求允许为止,其它进程允许进入临界区的次数有限

软件同步(Peterson算法)

该算法是一个基于软件的对临界区问题的解答,Peterson算法适用于两个进程在临界区和剩余区交替执行,该算法在两个进程共享两个数据项

  • int turn 表示哪个进程可以进入临界区
  • bool flag[2] 表示哪个进程请求进入临界区

turn = i 时,进程i允许进入临界区执行

硬件同步

任何临界区都需要一个简单工具 ;进入临界区要请求锁,退出临界区要释放锁

  • 在单处理器系统中,可以通过禁止中断来解决临界区问题
  • 在多处理器系统中,提供了特殊硬件指令以允许原子地(不可中断)执行一些操作

信号量

对于应用程序而言,解决临界区问题可用成为 信号量 的同步工具,信号量S是个整数变量,除了初始化外,只能通过两个标准原子操作:wait() 和 signal() 来访问;这些操作原来被称为PV原语(荷兰语proberen,测试;荷兰语verhogen,增加)

wait()的定义可表示为

1
2
3
4
5
6
7
8
wait(S){

    while(S <= 0){
        //循环等待
    }
    S--;

}

signal()的定义可表示为

1
2
3
4
signal(S){
    S++;
}

在PV操作中,对信号量的修改必须不可分地执行,即当一个进程修改信号量时不能有其它进程也在修改信号量

计数信号量的值域不受限制,二进制信号量的值只有0和1,经常称二进制信号量为互斥锁,因为可以提供互斥

自旋锁

上面所定义的信号量的主要缺点是忙等待;当一个进程进入临界区,任何试图进入其临界区的进程都必须在wait() 中无限循环等待,在多道程序系统中这显然是个问题,忙等待白白浪费了CPU的时钟;这类的信号量也称为自旋锁

为了克服忙等待,可以修改wait() 和 signal() 的定义

当一个进程执行wait() 必须等待时,该进程会阻塞自己,阻塞操作将一个进程放入到与信号量有关的等待队列中,并将该进程的状态切换成阻塞态

一个被阻塞的进程可以通过其它进程执行signal() 操作来唤醒,通过执行wakeup() ,该进程从阻塞态切换到就绪态,该进程会被调入到就绪队列中等待被调度

死锁和饥饿

死锁 :两个或多个进程无线等待一个事件,而该事件只能由等待进程之一来产生

饥饿 :无限期阻塞,进程在信号量内无线等待

OLDER POST NEWER POST

Comments powered by Disqus.

Search Results