欢迎访问有用文档网!

当前位置: 有用文档网 > 心得体会 >

进程(线程)同步和互斥实验报告

| 浏览次数:

  操 作 系 统 实 验 报 告 课程名称

 操作系统

 实验名称

 进程(线程)的同步与互斥

 成绩

  学生姓名

  作业君

  专业

  软件工程

  班级、学号

  同组者姓名

  无

  实验日期

 2020

  一、实验题目: : 进程(线程)的同步与互斥 二、实验目的 :

 自行编制模拟程序,通过形象化的状态显示,加深理解进程的概念、进程之间的状态转换及其所带来的 PCB 内容 、组织的变化,理解进程与其 PCB 间的一一对应关系。

 1.掌握基本的同步与互斥算法,理解生产者消费者模型。

 2.学习使用 Windows 中基本的同步对象,掌握相关 API 的使用方法。

 3.了解 Windows 中多线程的并发执行机制,实现进程的同步与互斥 三、实验内容与要求 :

 1.实验内容 以生产者/消费者模型为依据,在 Windows 环境下创建一个控制台进程,在该进程中创建 n 个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。

 2.实验要求 学习并理解生产者/消费者模型及其同步/互斥规则; 学习了解 Windows 同步对象及其特性; 熟悉实验环境,掌握相关 API 的使用方法; 设计程序,实现生产者/消费者进程(线程)的同步与互斥;

 四、算法描述(含数据结构定义)或流程图

 #include <Windows.h> #include <iostream> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std;

  #define MAX_THREAD_NUM 64

  //最大线程数 #define INTE_PER_SEC 1000

  //延迟时间的毫秒值 const int SIZE_OF_BUFFER = 10;

 //缓冲区长度 int ProductID = 0;

  //产品号 int ConsumeID = 0;

 //将被消耗的产品号 int in = 0;

 //产品进缓冲区时的缓冲区下标 int out = 0;

  //产品出缓冲区时的缓冲区下标 bool running = true;

 //判断程序能否继续执行的逻辑值 int g_buffer[SIZE_OF_BUFFER];

  //缓冲区是个循环队列 HANDLE g_hMutex;

 //公有信号量,用于线程间的互斥 HANDLE g_hFullSemaphore;

  //生产者的私有信号量,当缓冲区满时迫使生产者等待 HANDLE g_hEmptySemaphore;

  //消费者的私有信号量,当缓冲区空时迫使消费者等待

 //定义一个结构体用于存储线程的信息 struct ThreadInfo {

 int serial;

  //线程号

 char entity;

 //线程类别(生产者或消费者)

 double delay;

  //等待时间

 double persist; //操作时间 };

 //生产者 void Producer(void* p) {

 //定义变量用于存储当前线程的信息

 DWORD m_delay;

 DWORD m_persist;

 int m_serial;

  //从参数中获得信息

 m_serial = ((ThreadInfo*)(p))->serial;

 m_delay = (DWORD)(((ThreadInfo*)(p))->delay * INTE_PER_SEC);

 m_persist = (DWORD)(((ThreadInfo*)(p))->persist * INTE_PER_SEC);

  while (running)

 {

  //P 操作

  cout << "生产者线程 " << m_serial << " 请求生产." << endl;

  WaitForSingleObject(g_hEmptySemaphore, INFINITE);

  cout << "生产者线程 " << m_serial << " 请求独占缓冲区." << endl;

  WaitForSingleObject(g_hMutex, INFINITE);

 Sleep(m_delay);

 //延迟等待

  //生产一个产品

  cout << "生产者线程 " << m_serial << " 生产 " << ++ProductID << " 号产品成功." << endl;

  cout << "生产者线程 " << m_serial << " 请求将产品 " << ProductID << " 投入缓冲区." << endl;

  //把新生产的产品放入缓冲区

  g_buffer[in] = ProductID;

  in = (in +1)%SIZE_OF_BUFFER;

  Sleep(m_persist);

  //操作等待

  cout << "生产者线程 " << m_serial << " 将产品 " << ProductID << " 投入缓冲区中成功." << endl;

 //输出缓冲区当前的状态

  cout << "****************************" << endl

 << "\n 当前缓冲区情况如图(■代表已有产品,□代表没有产品):

  " << endl;

  for (int i = 0;i < SIZE_OF_BUFFER;++i)

  {

 if (g_buffer[i] != 0)

  cout << "■";

 else

 cout << "□";

  }

  cout << "\n\n****************************\n" << endl;

 //V 操作

  ReleaseMutex(g_hMutex);

  ReleaseSemaphore(g_hFullSemaphore, 1, NULL);

 } }

 //消费者 void Consumer(void* p) {

 DWORD m_delay;

 DWORD m_persist;

 int m_serial;

 //从参数中获得信息

 m_serial = ((ThreadInfo*)(p))->serial;

 m_delay = (DWORD)(((ThreadInfo*)(p))->delay * INTE_PER_SEC);

 m_persist = (DWORD)(((ThreadInfo*)(p))->persist * INTE_PER_SEC);

 while (running)

 {

  //P 操作

  cout << "消费者线程 " << m_serial << " 请求消费." << endl;

  WaitForSingleObject(g_hFullSemaphore, INFINITE);

  cout << "消费者线程 " << m_serial << " 请求独占缓冲区." << endl;

  WaitForSingleObject(g_hMutex,INFINITE);

 Sleep(m_delay); //延迟等待

  //从缓冲区中取出一个产品

  cout << "消费者线程 " << m_serial << " 请求取出一个产品." << endl;

  ConsumeID = g_buffer[out];

  g_buffer[out] = 0;

  out = (out + 1) % SIZE_OF_BUFFER;

  cout << "消费者线程 " << m_serial << " 取出产品 " << ConsumeID << " 成功." << endl;

 //消耗一个产品

  cout << "消费者线程 " << m_serial << " 开始消费消费产品 " << ConsumeID << "." << endl;

  Sleep(m_persist);

  cout << "消费者线程 " << m_serial << " 消费产品 " << ConsumeID << " 成功." << endl;

 //输出缓冲区当前的状态

  cout << "****************************" << endl

 << "\n 当前缓冲区情况如图:

  " << endl;

  for (int i = 0;i < SIZE_OF_BUFFER;++i)

  {

 if (g_buffer[i] != 0)

  cout << "■";

 else

 cout << "□";

  }

  cout << "\n\n****************************\n" << endl;

 //V 操作

  ReleaseMutex(g_hMutex);

  ReleaseSemaphore(g_hEmptySemaphore, 1, NULL);

 } }

 void prod_cons() {

 //创建互斥信号量

 g_hMutex = CreateMutex(NULL, FALSE, NULL);

 //创建同步信号量

 g_hEmptySemaphore = CreateSemaphore(NULL, SIZE_OF_BUFFER, SIZE_OF_BUFFER, NULL);

 g_hFullSemaphore = CreateSemaphore(NULL, 0, SIZE_OF_BUFFER, NULL);

 srand((unsigned)time(NULL));

 //以时间函数为种子

 const unsigned short THREADS_COUNT = rand() % 5 + 5; //总的线程数(随机生成)

  //线程对象的数组

 HANDLE hThreads[MAX_THREAD_NUM];

 ThreadInfo thread_info[MAX_THREAD_NUM];

  DWORD thread_ID; //线程 ID

 int num = 0;

  //临时变量,用于循环语句

 cout << "系统开始模拟,并自动生成模拟数据..." << endl;

 system("pause"); //暂停确认开始执行

 cout << "线程总数:" << THREADS_COUNT << endl;

  //循环随机生成各个线程的信息

 while (num != THREADS_COUNT)

 {

  thread_info[num].serial = num + 1;

  if (rand() % 2 == 1)

 thread_info[num].entity = "P";

  else

 thread_info[num].entity = "C";

  thread_info[num].delay = rand() % 5 + 1;

  thread_info[num].persist = rand() % 6 + 2;

  num++;

 }

  cout << "\n 系统生成数据结束,模拟数据如下:" << endl

  << "线程号

 线程类别

 延迟时间

 操作时间" << endl;

 for (int x = 0;x < THREADS_COUNT;x++)

  cout << "

 " << thread_info[x].serial << "\t"

  << "

  " << thread_info[x].entity << "\t"

  << "

 " << thread_info[x].delay << "\t\t"

  << "

  " << thread_info[x].persist << endl;

 cout << "\n\n==================生产者-消费者 开始==================\n" << endl;

  //创建线程

 for (int i = 0;i < THREADS_COUNT;i++)

 {

  //创建生产者线程

  if (thread_info[i].entity == "P")

 hThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(Producer), &thread_info[i], 0, &thread_ID);

  //创建消费者线程

  else

 hThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(Consumer), &thread_info[i], 0, &thread_ID);

 }

  while (running)

 {

  if (getchar())

  {

 //按回车后终止程序运行

 running = false;

  }

 }

 cout << "系统模拟结束..." << endl; } int main() {

 cout << "\n==================生产者-消费者 模拟==================\n" << endl;

 prod_cons(); }

 五、实验过程

 1、记录生产者和消费者的同步执行过程。

  2、分析 Producer 函数和 Consumer 函数的功能,并画出对应的程序流程图。

  Producer 函数:调用函数,获取资源情况,然后判断条件是否满足,判断是否执行,接着发出生产请求,请求通过后独占缓冲区资源,接着生产-一个产品投入缓冲区,成功后释放所占缓冲区资源,到此此函数执行完成。

 consumer 函数:

 通过用变量提取保存提取当前资源信息, 然后判断是否执行, 接着发出消费请求, 请求通过后独占缓冲区资源, 接着消费一个产品取出缓冲区, 成功后释放所占缓冲区资源, 到此此函数执行完成。

 3、试将同步和互斥的 P 操作颠倒次序执行,观察并分析程序的运行情况。

 答:

 如将同步和互斥的 P 操作颠倒次序执行,程序会产生死锁。因为这个操作会先独占缓冲区的资源,然后才发送请求。如果生产或者消费请求无法通过而一直等待下去的话,则无法释放资源,进而产生程序的死锁,使得程序无法运行!

 六、实验总结

 通过本次实验,让我对线程的同步与互斥技术有了比较深刻的了解,生产者消费者问题是研究多线线程程序绕不开的问题,它的描述是有一块生产者和消费者共享的有界缓冲区,生产者往缓冲区放入产品,消费者从缓冲区取走产品,这个过程可以无休止的进行,不能因缓冲区满生产者放不进产品而终止,也不能因缓冲区空消费者无产品可取而终止。

推荐访问:线程 进程 同步

热门排行Top Ranking

新时代青年的奋斗精神心得体会5篇

新时代青年的奋斗精神心得体会5篇新时代青年的奋斗精神心得体会篇1为进一步弘扬爱国奋斗奉献精神,激励党

XX乡镇防止返贫致贫监测和帮扶工作方案

XX乡镇防止返贫致贫监测和帮扶工作方案 为认真落实党的十九届四中全会关于“坚决打赢脱贫攻

坚持总体国家安全观心得体会250字8篇

坚持总体国家安全观心得体会250字8篇坚持总体国家安全观心得体会250字篇1“安而不忘危,存而不忘亡

宣传部部长心得体会15篇

宣传部部长心得体会15篇宣传部部长心得体会篇1首先,感谢领导给我这次评选优秀员工的机会,也感谢您能在

管理信息系统案例

第一章 信息系统与管理 案例((或实例) 得讨论题及点评((或回答)) [实例]利润计划工作中得反复

大学生体育课心得体会1500字5篇

大学生体育课心得体会1500字5篇大学生体育课心得体会1500字篇1不知不觉,进入大学第一个学期的体

餐饮单位疫情防控工作汇报

餐饮单位疫情防控工作汇报根据省、市、区疫情防控指挥部统一部署,严格落实《省市场监督管理局关于进一步加

党支部党建工作年度台账-基层党建工作台账

党支部党建工作年度台账::基层党建工作台账 党支部党建工作年度台账说明为抓好党建工作,根据《党章》《

党员的时代楷模心得体会12篇

党员的时代楷模心得体会12篇党员的时代楷模心得体会篇1@党员干部“打工攻略”请查收一年一度的“双十一

公文格式国家标准

公文格式国家标准 1范围 本标准规定了党政机关公文通用的纸张要求、排版和印制装订要求、公文格式各要素

内勤辅警先进事迹材料

内勤辅警先进事迹材料3篇 内勤辅警先进事迹材料1 办公室工作室一项既辛苦、又清苦的脑力劳动,他没有惊

傅雷家书阅读心得及感悟10篇

傅雷家书阅读心得及感悟10篇傅雷家书阅读心得及感悟篇1一连几天,我都沉浸在《傅雷家书》这本书中,感受