用PV操作解决生产者消费者问题

操作系统进程相关:用PV操作解决生产者消费者问题。

问题描述

当进程并发执行时,如果对进程访问的共享变量不加限制,就会产生“与时间有关”的错误。为了防止这类错误,系统必须用同步机构来控制进程对共享变量的访问。一般说,同步机构是由若干条同步原语所组成。本实验要求模拟PV操作实现同步机构,且用PV操作解决生产者—消费者问题。

参考

操作系统中的P,V操作

代码实现

1
#include <iostream>
2
#include <string>
3
#include <ctime>
4
using namespace std;
5
#define DO_NUM 30 // 调度次数
6
7
// 进程控制块PCB
8
struct PNode {
9
    string name;        // 进程名
10
    string state;       // 状态
11
    string reason;      // 等待原因
12
    int breaking;       // 断点
13
} produce, consume, *run, *ready; // 生产者进程、消费者进程、当前运行进程、当前就绪进程
14
15
// 初始化数据结构
16
int s1 = 10, s2 = 0, PC; // 两个信号量,程序计数器PC
17
int PA[5]; // PA[i]存放生产者程序中的一条模拟指令执行的入口地址
18
int SA[5]; // SA[i]存放消费者程序中的一条模拟指令执行的入口地址
19
int IN = 0, OUT = 0; // 进出缓冲期的位置
20
char product, X; // 生产的产品、消费的产品
21
char B[10]; // 缓冲器
22
23
// 初始化程序
24
void init() {
25
    for(int i=0; i<5; i++) {
26
        PA[i] = i;
27
        SA[i] = i;
28
    }
29
    produce.name = "Produce";
30
    produce.state = "Ready"; // 生产者就绪
31
    produce.breaking = 0; // 断点为0
32
    consume.name = "Consume";
33
    consume.state = "Ready"; // 消费者就绪
34
    consume.breaking = 0; // 断点为0
35
    PC = 0;
36
}
37
38
// 处理机调度程序
39
void schedule() {
40
    if(produce.state=="Ready" && consume.state=="Ready") {
41
        srand((unsigned)time(NULL));
42
        int a = rand() % 2; // 随机数 0或1
43
        if(a == 1) {
44
            run = &produce; // 生产者进程运行
45
            ready = &consume; // 消费者进程就绪
46
        }else {
47
            run = &consume; // 消费者进程运行
48
            ready = &produce; // 生产者进程就绪
49
        }
50
    }else if(produce.state=="Ready" && consume.state=="Wait") {
51
        run = &produce; // 生产者进程运行
52
        ready = &consume; // 消费者进程就绪
53
    }else if(produce.state=="Wait" && consume.state=="Ready") {
54
        run = &consume; // 消费者进程运行
55
        ready = &produce; // 生产者进程就绪
56
    }
57
    PC = run->breaking; // 设置断点保护现场
58
}
59
60
// 处理器执行指令程序
61
void perform() {
62
    if(run->name == "Produce") { // 当前生产者程序在运行
63
        int j = PA[PC++]; // 生产者程序指令执行的入口地址
64
        switch(j) {
65
            case 0: cout << "生产!请输入一个字符 > "; cin >> product; break; // produce
66
            case 1: // P(s1)
67
                s1--;
68
                if(s1 < 0) {
69
                    run->state = "Wait";
70
                    run->reason = "s1";
71
                    cout << "生产者等待原因: " << run->reason << endl;
72
                }else run->state = "Ready";
73
                break;
74
            case 2: // PUT
75
                B[IN] = product;
76
                IN = (IN + 1) % 10;
77
                cout << "缓冲器内容: ";
78
                for(int i=0; i<10; i++)
79
                    cout << B[i] << " ";
80
                cout << endl;
81
                break;
82
            case 3: // V(s2)
83
                s2++;
84
                if(s2 <= 0)	ready->state = "Ready";
85
                else	run->state = "Ready";
86
                break;
87
            case 4: PC = 0; break; // GOTO 0
88
        }
89
        run->breaking = PC; // 设置断点保护现场
90
    }else { // 当前消费者程序在运行
91
        int j = SA[PC++]; // 消费者程序指令执行的入口地址
92
        switch(j) {
93
            case 0: // P(s2)
94
                s2--;
95
                if(s2 < 0) {
96
                    run->state = "Wait";
97
                    run->reason = "s1";
98
                    cout << "消费者等待原因: " << run->reason << endl;
99
                }else run->state = "Ready";
100
                break;
101
            case 1: X = B[OUT]; OUT = (OUT + 1) % 10; break; // GET
102
            case 2: // V(s1)
103
                s1++;
104
                if(s1 <= 0)	ready->state = "Ready";
105
                else	run->state = "Ready";
106
                break;
107
            case 3: cout << "消费!显示消费的结果 > " << X << endl; break; // consume
108
            case 4: PC = 0; break; // GOTO 0
109
        }
110
        run->breaking = PC; // 设置断点保护现场
111
    }
112
}
113
114
int main() {
115
    init(); // 初始化程序
116
    cout << "**用PV操作解决生产者消费者问题**" << endl;
117
    for(int i=0; i<DO_NUM; i++) {
118
        schedule(); // 处理机调度
119
        perform(); // 处理机执行指令
120
    }
121
    return 0;
122
}