【操作系统总结】进程同步的信号量机制

信号量机制是由dijkstra 1965年提出,是解决进程同步重要的工具

下面方法适用与几个进程访问同一个临界区

整形信号量

定义一个表示资源数目的整形信号量S,仅能同步P, V操作改变。原始值S=1,每一个进程来的时候会执行:

  1. 首先执行wait()操作,如果信号量s<=0就会一直检测并阻塞
  2. 如果不小于0就会进入临界区,并把S设为0,保证其他进程无法进去临界区
  3. 在临界区执行完,再把信号量设置回来。
wait(S) {
    while(S <= 0);//资源如果小余0就会阻塞。一直在这边检测
    S--;//进入临界区就会将
}

signal(S) {
    S ++;//在临界区执行完了,就会把信号量+1
}

记录型信号量

整形信号量没有遵循”让权等待原则”,进程一但进不去临界区就在那一直检测,不释放处理机,所以有了记录型信号量

  1. 首先一个进程请求该类资源,执行wait操作,发现value<0,就进入阻塞,插入链表,释放处理机
  2. 另外一个进程不再使用该资源了,就会执行signal操作,发现value小于0,就会唤醒链表中的阻塞队列

信号量S是一个结构

typedef struct {
    int value;//表示资源数目的整形变量
    struct process_control_block *list;//进程链表,阻塞的进程都会放到这里
}
wait(semaphore *S) {
    S->value--;//首先执行wait操作,就将value-1,
    if(S->value < 0) bolck(S->list);//如果发现value小于0,就会阻塞,把进程放入链表中
}

signal(semaphore *S) {
    S->value ++;//让value+1
    if(S->value <= 0) wakeup(S->list);//如果发现还是小于0,证明还有进程在阻塞,唤醒链表中的第一个进程
}

下面是针对多个并发进程访问多个临界资源

AND型信号量

AND型信号量思想,就是把进程整个运行中需要的资源,一次性的全部分配给他,然后进程执行完了,再一次性释放。如果有一个未分配,其他资源也不分配给这个进程,这样就可以避免死锁问题

  1. 进程先执行Swait操作,如果所有资源都可以分配,就把所有资源分配给这个进程
  2. 当进程执行完了,就会Ssignal操作释放资源,然后唤醒等待队列中另一个进程
Swait(S1, S2,.........Sn) {
    while(true) {
        if(S1>=1&&....&&Sn>=1) {//检测所有的资源都可以分配
            for(i = i; i<n; i++) {
                for(i = i; i<n; i++) Si--;//所有的资源数量-1
                break;
            }
        }
        else {
            //进入阻塞队列,等待资源
        }
    }
}

Ssignal(S1, S2,......Sn) {
    while(true) {
    for(i=1; i<n;i++) {//释放所有的资源
            Si++;
            //唤醒等待队列中的进程
        }
    }
}

信号量集

上面的只能对信号量执行+1或者-1操作,每次只能对资源进行一个单位的申请或者释放,当需要N个单位的时候,就要执行N此wait操作,这样很低效

机遇AND型信号量的扩充—>信号量集

  1. 该资源的分配下限是ti
  2. 当资源Si高于他的分配下限的时候可以分配也就是 Si > ti;
  3. di是进程对该资源的需求量,分配资源以后要进程Si = Si - di
  4. 当进程不需要资源的时候,释放就要进行Si = Si + di;
Swait(S1, t1, d1,.........Sn, tn, dn) {
    while(true) {
        if(S1>=t1&&....&&Sn>=tn) {//检测所有的资源都可以分配
            for(i = i; i<n; i++) {
                for(i = i; i<n; i++) Si = Si - di;//所有的资源数量d1,所需的资源量
                break;
            }
        }
        else {
            //进入阻塞队列,等待资源
        }
    }
}

Ssignal(S1, d1,......Sn, dn) {
    while(true) {
    for(i=1; i<n;i++) {//释放所有的资源
            Si = Si + di;
            //唤醒等待队列中的进程
        }
    }
}

特殊情况

  1. Swait(S, d, d)只有一个信号量,也就是只需要这一个资源,现有资源不能小余d
  2. Swait(S, 1, 1)就是一般的信号量机制(整形信号量机制)
  3. Swait(S, 1, 0)当S >= 1时,允许多个进程进入临界区,否则就会组织任何进程进入临界区

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。