「操作系统」PV大题经典算法模版
本文最后更新于125 天前,其中的信息可能已经过时,如有错误请发送邮件到1910452164@qq.com

这是一篇针对操作系统考研中 PV操作(信号量机制) 经典大题的解题模板总结。在考试中,解答此类题目通常需要遵循 “定义信号量 -> 编写进程伪代码” 的步骤。

以下是四大经典模型的标准解题模板:

生产者-消费者模型

这是最基础也是最重要的模型,核心在于处理缓冲区的互斥访问以及缓冲区满/空的同步问题。

 解题关键

  • 互斥信号量 (mutex):保护缓冲区,防止同时存取。
  • 同步信号量 (full/empty)
    • full:表示缓冲区中“产品”的数量(初值为0)。
    • empty:表示缓冲区中“空位”的数量(初值为N)。

标准代码模板

semaphore mutex = 1;  // 临界区互斥信号量
semaphore empty = N;  // 空缓冲区数量
semaphore full = 0;   // 满缓冲区数量(产品数)

// 生产者进程
void Producer() {
    while(true) {
        produce_item();      // 生产一个产品

        P(empty);            // 申请一个空位 (若无空位则阻塞)
        P(mutex);            // 申请进入缓冲区 (互斥)
        
        put_item();          // 将产品放入缓冲区
        
        V(mutex);            // 退出缓冲区
        V(full);             // 释放一个产品信号 (通知消费者)
    }
}

// 消费者进程
void Consumer() {
    while(true) {
        P(full);             // 申请一个产品 (若无产品则阻塞)
        P(mutex);            // 申请进入缓冲区
        
        take_item();         // 从缓冲区取出一个产品
        
        V(mutex);            // 退出缓冲区
        V(empty);            // 释放一个空位信号 (通知生产者)
        
        consume_item();      // 消费产品
    }
}

哲学家进餐问题

核心在于死锁(Deadlock)的预防。如果是普通的教科书式解法(每人先拿左再拿右),会导致死锁。考研中通常建议使用“限制策略”“奇偶分层策略”来作为标准答案。

解题关键

  • 资源信号量:5根筷子,每根是一个信号量。
  • 死锁解决
    • 方案A:仅当左右两根筷子都可用时才拿(需要在一个临界区内判断)。
    • 方案B:限制最多4人同时进餐。
    • 方案C(推荐模板):奇数号哲学家先拿左边,偶数号哲学家先拿右边。

标准代码模板 (奇偶策略防死锁版)

semaphore chopstick[5] = {1, 1, 1, 1, 1}; // 5根筷子

void Philosopher(int i) { // i 为哲学家编号 0-4
    while(true) {
        think(); // 思考
        
        if (i % 2 == 0) {
            // 偶数号哲学家:先拿左(i),后拿右((i+1)%5)
            P(chopstick[i]);
            P(chopstick[(i + 1) % 5]);
        } else {
            // 奇数号哲学家:先拿右((i+1)%5),后拿左(i)
            // 这样打破了环路等待条件
            P(chopstick[(i + 1) % 5]);
            P(chopstick[i]);
        }

        eat(); // 进餐

        // 放下筷子(顺序无所谓,通常怎么拿怎么放)
        V(chopstick[i]);
        V(chopstick[(i + 1) % 5]);
    }
}

读者-写者模型

核心在于处理“读-读允许,读-写互斥,写-写互斥”。最常考的是“读者优先”(只要有读者在读,后来的读者可以直接进,写者必须等所有读者走完)。

解题关键

  • 读写互斥 (rw):控制写者与读者的互斥。
  • 计数器 (count):记录当前读者的数量。
  • 计数器互斥 (mutex):保护 count 变量的修改。

标准代码模板 (读者优先)

int count = 0;       // 记录当前读者数量
semaphore mutex = 1; // 保护 count 变量
semaphore rw = 1;    // 保证读者和写者互斥访问文件

// 写者进程
void Writer() {
    while(true) {
        P(rw);       // 申请写权限 (若有读者或写者在操作则阻塞)
        
        writing();   // 写操作
        
        V(rw);       // 释放写权限
    }
}

// 读者进程
void Reader() {
    while(true) {
        P(mutex);        // 申请修改 count
        if (count == 0) {
            P(rw);       // 如果是第一个读者,负责锁住写者
        }
        count++;
        V(mutex);        // 释放 count 锁
        
        reading();       // 读操作 (多个读者可同时在此处)
        
        P(mutex);        // 申请修改 count
        count--;
        if (count == 0) {
            V(rw);       // 如果是最后一个读者,负责释放写者
        }
        V(mutex);        // 释放 count 锁
    }
}

理发师模型

这是一个典型的服务排队模型。核心在于理发师在无顾客时睡眠,顾客来时唤醒理发师;若理发师忙,顾客判断是否有空位等待。

解题关键

  • 变量 waiting:记录等待理发的顾客数。
  • 信号量 customers:表示等待的顾客数量(用来唤醒理发师)。
  • 信号量 barbers:表示理发师的状态(0表示忙或睡,1表示准备好/空闲,或者用来阻塞顾客)。
  • 互斥 mutex:保护 waiting 变量。

标准代码模板

semaphore customers = 0; // 等待理发的顾客数 (同步)
semaphore barbers = 0;   // 理发师空闲信号 (同步)
semaphore mutex = 1;     // 互斥访问 waiting 变量
int waiting = 0;         // 等待椅上的人数
int CHAIRS = N;          // 椅子总数

// 理发师进程
void Barber() {
    while(true) {
        P(customers);    // 等待顾客 (若无顾客则睡觉/阻塞)
        P(mutex);        // 申请访问 waiting
        
        waiting--;       // 等待人数 -1
        V(barbers);      // 发信号:理发师准备好了/开始理发
        
        V(mutex);        // 释放 waiting 访问权
        
        cut_hair();      // 理发 (非临界区)
    }
}

// 顾客进程
void Customer() {
    P(mutex);            // 申请访问 waiting
    
    if (waiting < CHAIRS) {
        waiting++;       // 还有空位,坐下等待
        V(customers);    // 唤醒理发师 (或是增加一个顾客信号)
        V(mutex);        // 释放 waiting 访问权
        
        P(barbers);      // 等待理发师叫号 (阻塞直到理发师空闲)
        get_haircut();   // 接受理发
    } else {
        V(mutex);        // 没空位了,直接离开
        leave();         
    }
}

注意,这里的customer进程中没有while(true)的循环,只有一个if-else的分支判断。

评论

  1. 郭琪琪
    Windows Edge
    4 月前
    2025-12-25 16:55:00

    不会

  2. 郭琪琪
    Windows Edge
    4 月前
    2025-12-25 16:56:59

    我真的不会

  3. 去玩儿
    Windows Edge
    4 月前
    2025-12-25 16:57:50

    不会不会不会

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇