计算机操作系统实验报告:进程同步与互斥
进程同步与互斥。
计算机操作系统实验报告:
一.进程同步与互斥
1.实验名称:
进程同步与互斥
2.实验目的:
两个或两个以上的进程,不能同时进入关于同一组共享变量的临界区域,否则可能发生与时间有关的错误,这种现象被称作进程互斥。对CPU的速度和数目不做出任何的假设的前提下,并发进程互斥访问临界资源,是一个较好的解决方案。另外,还需要解决异步环境下的进程同步问题。所谓异步环境是指:相互合作的一组并发进程,其中每一个进程都以各自独立的、不可预知的速度向前推进;但它们又需要密切合作,以实现一个共同的任务,即彼此“知道”相互的存在和作用。
实验目的:分析进程争用资源的现象,学习解决进程同步与互斥的方法。
本实验属于设计型实验,实验者可根据自身情况选用合适的开发环境和程序架构。
3.实验原理:
信号量的PV操作与处理相关,P表示通过的意思,V表示释放的意思。所谓信号量,实际上就是用来控制进程状态的一个代表某一资源的存储单元。例如,P1和P2是分别将数据送入缓冲B和从缓冲B读出数据的两个进程,为了防止这两个进程并发时产生错误,狄克斯特拉设计了一种同步机制叫“PV操作”,P操作和V操作是执行时不被打断的两个操作系统原语。执行P操作P(S)时信号量S的值减1,若结果不为负则P(S)执行完毕,否则执行P操作的进程暂停以等待释放。执行V操作V(S)时,S的值加1,若结果不大于0则释放一个因执行P(S)而等待的进程。对P1和P2可定义两个信号量S1和S2,初值分别为1和0。进程P1在向缓冲B送入数据前执行P操作P(S1),在送入数据后执行V操作V(S2)。进程P2在从缓冲B读取数据前先执行P操作P(S2),在读出数据后执行V操作V(S1)。当P1往缓冲B送入一数据后信号量S1之值变为0,在该数据读出后S1之值才又变为1,因此在前一数未读出前后一数不会送入,从而保证了P1和P2之间的同步。
这一同步机制叫PV操作,这是狄克斯特拉用荷兰文定义的,因为在荷兰文中,通过叫passeren,释放叫vrijgeven,PV操作因此得名。这是在计算机术语中不是用英语表达的极少数的例子之一。
4.仪器与材料:
PC机,Devc++。
5.实验步骤(代码):
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
const int SIZE_OF_BUFFER = 2;
int ProductID = 0;
int ConsumeID = 0;
int in = 0;
int out = 0;
int buffer[SIZE_OF_BUFFER];
bool p_ccontinue = true;
std::mutex mtx;
std::condition_variable full_cv;
std::condition_variable empty_cv;
void Produce() {
std::cout << "Producing " << ++ProductID << "......succeed" << std::endl;
}
void Append() {
std::cerr << "Appending a product ... ";
buffer[in] = ProductID;
in = (in + 1) % SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;
// 输出缓冲区当前状态
for (int i = 0; i < SIZE_OF_BUFFER; i++) {
std::cout << i << ":" << buffer[i];
if (i == in) std::cout << "<----生产";
if (i == out) std::cout << "<-----消费";
std::cout << std::endl;
}
}
void Take() {
std::cerr << "Taking a product . . .";
ConsumeID = buffer[out];
buffer[out] = 0;
out = (out + 1) % SIZE_OF_BUFFER;
std::cerr << "Succeed" << std::endl;
// 输出缓冲区当前状态
for (int i = 0; i < SIZE_OF_BUFFER; i++) {
std::cout << i << ":" << buffer[i];
if (i == in) std::cout << "<----生产";
if (i == out) std::cout << "<-----消费";
std::cout << std::endl;
}
}
void Consume() {
std::cout << "Consuming " << ConsumeID << "...succeed" << std::endl;
}
void ProducerFunction() {
while (p_ccontinue) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
Produce();
{
std::unique_lock<std::mutex> lock(mtx);
Append();
}
full_cv.notify_all();
}
}
void ConsumerFunction() {
while (p_ccontinue) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::unique_lock<std::mutex> lock(mtx);
full_cv.wait(lock, [] { return !p_ccontinue || buffer[out] != 0; });
if (!p_ccontinue) return;
Take();
Consume();
empty_cv.notify_all();
}
}
int main() {
std::vector<std::thread> producers;
std::thread consumer(ConsumerFunction);
for (int i = 0; i < 3; i++) {
producers.emplace_back(ProducerFunction);
}
for (auto& producer : producers) {
producer.join();
}
p_ccontinue = false;
consumer.join();
return 0;
}
6.问题即讨论
一个仓库可以存放K件物品。生产者每生产一件产品,将产品放入仓库,仓库满了就停止生产。消费者每次从仓库中去一件物品,然后进行消费,仓库空时就停止消费。
7.运行结果
**Producing 1…succeed
Appending a product …
Succeed
0:1<-----消费
1:0<----生产
Producing 2…succeed
Appending a product …
Succeed
0:1<----生产<-----消费
1:2
Taking a product . . .
Succeed
0:0<----生产
1:2<-----消费
Consuming 1…succeed
Taking a product . . .
Succeed
0:0<----生产<-----消费
1:0
Consuming 2…succeed
Producing 3…succeed
Appending a product …
Succeed
0:3<-----消费
1:0<----生产
Producing 4…succeed
Appending a product …
Succeed
0:3<----生产<-----消费
1:4
Taking a product . . .
Succeed
0:0<----生产
1:4<-----消费
Consuming 3…succeed
Taking a product . . .
Succeed
0:0<----生产<-----消费
1:0
Consuming 4…succeed
Producing 5…succeed
Appending a product …
Succeed
0:5<-----消费
1:0<----生产
Producing 6…succeed
Appending a product …
Succeed
0:5<----生产<-----消费
1:6
Taking a product . . .
Succeed
0:0<----生产
1:6<-----消费
Consuming 5…succeed
Producing 7…succeed
Appending a product …
Succeed
0:7
1:6<----生产<-----消费
**
更多推荐
所有评论(0)