计算机基础知识
  • 关于
  • 系统
    • 操作系统的概念、功能、目标
    • 操作系统的特征
    • 并发和并行的区别
    • 操作系统的发展与分类
    • 操作系统的运行机制和体系结构
    • 中断和异常
    • 用户态、核心态之间的切换是怎么实现的?
    • 系统调用
    • 进程的概念
    • 进程的状态和转换
    • 进程控制
    • 进程通信
    • 线程、多线程模型
    • 程序、进程和作业的关系
    • 处理机调度的概念、层次
    • 进程调度的时机、切换与过程、方式
    • 调度算法的评价指标
    • 批处理系统的调度算法
    • 交互式系统的调度算法
    • 进程同步与进程互斥
    • 进程互斥的软件实现方法
    • 进程互斥的硬件实现方法
    • 信号量机制
    • 用信号量机制实现进程互斥、同步、前驱关系
    • 生产者-消费者问题
    • 多生产者-多消费者问题
    • 吸烟者问题
    • 读者-写者问题
    • 哲学家进餐问题
    • 管程
    • 死锁的概念
    • 死锁的处理策略——预防死锁
    • 死锁的处理策略——避免死锁
    • 死锁的处理策略——检测和解除
  • 网络
    • 计算机网络的概念、组成、功能、分类
    • 标准化工作及相关组织
    • 性能指标之速率、带宽、吞吐量
    • 性能指标之时延、时延带宽积、往返时间RTT、利用率
    • 分层结构
    • OSI参考模型
    • TCP/IP参考模型
    • 5层参考模型
    • http与https的区别
    • TCP和UDP的区别
  • Java
    • Arraylist与LinkedList区别
    • HashMap,HashTable,ConcurrentHash的共同点和区别
  • 数据库
    • 为什么MySQL索引要使用B+树
由 GitBook 提供支持
在本页
  • 引入
  • 概念
  • 整型信号量
  • 记录型信号量
在GitHub上编辑
  1. 系统

信号量机制

引入

在双标志先检查法中,进入区的“检查”、“上锁”操作无法一气呵成,从而导致了两个进程有可能同时进入临界区的问题;

所有的解决方案都无法实现“让权等待”

1965年,荷兰学者Dijkstra提出了一种卓有成效的实现进程互斥、同步的方法一一信号量机制

概念

用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。

信号量其实就是一个变量(可以是一个整数,也可以是更复杂的记录型变量),可以用一个信号量来表示系统中某种资源的数量,比如:系统中只有一台打印机,就可以设置一个初值为1的信号量。

原语是一种特殊的程序段,其执行只能一气呵成,不可被中断。原语是由关中断/开中断指令实现的。软件解决方案的主要问题是由“进入区的各种操作无法一气呵成”,因此如果能把进入区、退出区的操作都用“原语”实现,使这些操作能“二气呵成”就能避免问题。

一对原语:wait(S)原语和signal(S)原语,可以把原语理解为我们自己写的函数,函数名分别为wait和signal,括号里的信号量S其实就是函数调用时传入的一个参数。

wait、signal原语常简称为P、V操作(来自荷兰语proberen和verhogen)。因此,做题的时候常把wait(S)、signal(S)两个操作分别写为P(S)、V(S)

整型信号量

用一个整数型的变量作为信号量,用来表示系统中某种资源的数量。

int S = 1; // 初始化整型信号量s,表示当前系统中可用的资源

void wait (int S) { //wait原语,相当于"进入区”
    while(S <= 0); // 如果资源数不够,就一直循环等待
    S = S - 1; // 如果资源数够,则占用一个资源
}

void signal (int S) { // signal原语,相当于"退出区”
    S = S + 1; // 使用完资源后,在退出区释放资源
}

记录型信号量

整型信号量的缺陷是存在“忙等”问题,因此人们又提出了“记录型信号量”,即用记录型数据结构表示的信号量。

/*记录型信号量的定义*/
type def struct{
    int value; // 剩余资源数
    Struct process *L; // 等待队列
} semaphore;

/*某进程需要使用资源时,通过wait原语申请*/
void wait (semaphore S) {
    S.value--;
    if(S.value < 0){
        block(S.L);
    }
}

/*进程使用完资源后,通过signal原语释放*/
void signal (semaphore S) {
    s.value++;
    if(S.value <= 0){
        wake up(S.L);
    }
}

S.value的初值表示系统中某种资源的数目。

对信号量S的一次P操作意味着进程请求一个单位的该类资源,因此需要执行S.value-,表示资源数减1,当S.value<0时表示该类资源已分配完毕,因此进程应调用block原语进行自我阻塞(当前运行的进程从运行态→阻塞态),主动放弃处理机,并插入该类资源的等待队列S.L中。可见,该机制遵循了“让权等待”原则,不会出现“忙等”现象。

对信号量S的一次V操作意味着进程释放一个单位的该类资源,因此需要执行S.value++,表示资源数加1,若加1后仍是S.value<=0,表示依然有进程在等待该类资源,因此应调用wakeup原语唤醒等待队列中的第一个进程(被唤醒进程从阻塞态→就绪态)。

最后更新于2年前