9 信号量和管程

信号量

  1. 锁的不足

    • 多线程同时执行访问临界区
    • 互斥和条件同步
  2. 含义

    • 包含一个信号量sem(semaphore,有符号整数) 和两个原子操作:P操作和V操作
      image-20200831205541061
    • sem变量受保护。初始化后,改变信号量的唯一方法是P()和V()。两个操作必须是原子的
    • P()能够阻塞,V()不会阻塞
    • 假定信号量是公平的:实践中,通常使用FIFO,利用队列决定唤醒哪个进程 ⇒ 上一章的Spinlock是FIFO类型吗?
  3. 用途

    • 互斥
    • 条件同步(调度约束 —— 一个进程等待另一个进程的事件发生)
  4. 两种类型信号量

    • 二进制信号量:0或1 ⇒ 模拟lock操作

      • 模拟lock操作

        mutex = new Semaphore(1); //sem初值置1
        ...
        mutex->P();
            ...
        Critical Section;
            ...
        mutex->V();
        
      • 实现简单的调度/同步约束(线程A的P()后面的代码需等待线程B执行到V()后才继续执行)

        image-20200831211716958

    • 一般/计数信号量:可取任何非负值

      • 解决复杂的调度/同步问题

      • image-20200831213958714

      • image-20200831214038346

      • image-20200831214420538

  5. 信号量的实现

    class Semaphore{
        int sem;
        waitQueue q;
    }
    Semaphore::P(){ //该原子操作的语义
        sem--;
        if(sem < 0){
            Add this thread t to q;
            block(t);
        }
    }
    Semaphore::V(){ //该原子操作的语义
        sem++;
        if(sem <= 0){
            Remove a thread t from q;
            wakeup(t);
        }
    }
    
  6. 不足

    • 读/开发代码比较困难
      • 程序员必须非常精通信号量
    • 容易出错
      • 使用的信号量被另一个线程占用
      • 忘记释放信号量
    • 不能解决死锁问题

管程

  1. 抽象程度比信号量更高。处于语言层面
  2. 目的:分离互斥和条件同步的关注
posted @ 2022-02-16 14:12  DreamEagle  阅读(43)  评论(0编辑  收藏  举报