进程(线程)的同步与互斥实验报告
- 格式:doc
- 大小:108.00 KB
- 文档页数:8
进程(线程)同步和互斥实验报告操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期2021一、实验题目: : 进程(线程)的同步与互斥二、实验目的:自行编制模拟程序,通过形象化的状态显示,加深理解进程的概念、进程之间的状态转换及其所带来的 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 MA__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;//判断程序能否继续执行的逻辑值 intg_buffer[SIZE_OF_BUFFER];//缓冲区是个循环队列 HANDLE g_hMute_;//公有信号量,用于线程间的互斥 HANDLEg_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_hMute_, 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 << “■”;elsecout << “□”;}cout << “\n\n____________________________\n” << endl;//V 操作ReleaseMute_(g_hMute_);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_hMute_,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 << “■”;elsecout << “□”;}cout << “\n\n____________________________\n” << endl;//V 操作ReleaseMute_(g_hMute_);ReleaseSemaphore(g_hEmptySemaphore, 1, NULL);} }void prod_cons {//创建互斥信号量g_hMute_ = CreateMute_(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[MA__THREAD_NUM];ThreadInfo thread_info[MA__THREAD_NUM];DWORD thread_ID; //线程 IDint 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";elsethread_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 _ = 0;_ < THREADS_COUNT;_++)cout << “” << thread_info[_].serial << “\t”<< “” << thread_info[_].entity << “\t”<< “” << thread_info[_].delay << “\t\t”<< “” << thread_info[_].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);//创建消费者线程elsehThreads[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、记录生产者和消费者的同步执行过程。
实验1编程实现进程同步和互斥进程(线程)同步和互斥是操作系统中非常重要的概念,它们用于控制多个进程(线程)之间的访问顺序,以确保数据的一致性和正确性。
在本文中,我们将详细介绍进程(线程)同步和互斥的概念,并通过编程实现来说明它们的具体应用。
1.进程(线程)同步的概念进程(线程)同步是指多个进程(线程)之间按照一定的顺序访问共享的资源,以避免竞争条件(race condition)和数据不一致的问题。
在并发环境下,多个进程(线程)同时访问共享的资源时,可能会遇到互相干扰的情况,导致程序的执行结果出现错误。
2.进程(线程)互斥的概念进程(线程)互斥是指在同一时间只能有一个进程(线程)对共享资源进行访问,其他进程(线程)必须等待当前进程(线程)释放资源后才能访问。
通过引入互斥机制,可以避免多个进程(线程)同时对共享资源进行写操作,从而保证数据的一致性和正确性。
3.进程(线程)同步和互斥的实现在实际编程中,可以通过各种同步和互斥机制来实现进程(线程)同步和互斥。
常见的机制有信号量(Semaphore)、互斥锁(Mutex)、条件变量(Condition Variable)等。
下面我们将通过一个简单的编程实例来演示如何使用信号量和互斥锁实现进程(线程)同步和互斥。
假设有两个线程,线程A负责打印奇数,线程B负责打印偶数,要求线程A和线程B交替打印1-100的数字。
我们可以使用互斥锁来控制两个线程的访问顺序,使用信号量来控制线程A和线程B的打印顺序。
首先,我们定义一个全局变量num,用来记录当前需要打印的数字。
定义一个互斥锁mutex,用来保护对num的访问。
定义一个信号量sem,用来控制线程A和线程B的打印顺序。
初始时,num为1,mutex为未锁定状态,sem的初始值为0。
线程A的处理函数如下:```void* threadA(void* arg)while (num <= 100)//等待信号量semsem_wait(&sem);//加锁pthread_mutex_lock(&mutex);//打印奇数if (num <= 100)printf("%d\n", num);num += 2;}//解锁pthread_mutex_unlock(&mutex);//发送信号量给线程Bsem_post(&sem);}return NULL;```线程B的处理函数如下:```void* threadB(void* arg)while (num <= 100)//等待信号量semsem_wait(&sem);//加锁pthread_mutex_lock(&mutex);//打印偶数if (num <= 100)printf("%d\n", num);num += 2;}//解锁pthread_mutex_unlock(&mutex);//发送信号量给线程Asem_post(&sem);}return NULL;```在主函数中创建两个线程,并执行线程:```int maipthread_t tidA, tidB;//初始化互斥锁pthread_mutex_init(&mutex, NULL);//初始化信号量sem_init(&sem, 0, 1);//创建线程Apthread_create(&tidA, NULL, threadA, NULL); //创建线程Bpthread_create(&tidB, NULL, threadB, NULL);//等待线程A结束pthread_join(tidA, NULL);//等待线程B结束pthread_join(tidB, NULL);//销毁互斥锁pthread_mutex_destroy(&mutex);//销毁信号量sem_destroy(&sem);return 0;```通过运行以上代码,我们可以看到线程A和线程B会交替打印1-100的数字,实现了进程(线程)的同步和互斥。
进程的同步与互斥实验报告1.实验目的进程(线程)的同步与互斥是操作系统中非常重要的概念,本实验旨在通过实际操作,加深对这些概念的理解和掌握。
通过编写多个进程(线程),并在其间进行同步与互斥操作,验证同步与互斥的实际效果。
2.实验环境本实验在Linux系统下进行,使用C/C++语言编程。
3.实验内容3.1同步在实验中,我们编写了两个进程A和B,这两个进程需要按照特定的顺序执行。
为了实现同步,我们使用信号量机制来确保进程A和B按照正确的顺序执行。
3.2互斥在实验中,我们编写了多个进程C和D,这些进程需要同时对一个共享资源进行访问。
为了实现互斥,我们使用互斥锁机制来确保同一时刻只有一个进程访问共享资源。
4.实验过程4.1同步实验编写进程A和进程B的代码,使用信号量机制实现同步。
进程A先运行,然后通过信号量唤醒进程B,进程B再开始执行。
通过观察进程的运行顺序,验证同步机制是否起作用。
4.2互斥实验编写进程C和进程D的代码,使用互斥锁机制实现互斥。
进程C和进程D同时对一个共享资源进行访问,通过互斥锁来确保同一时刻只有一个进程访问共享资源。
观察进程的输出结果,验证互斥机制是否起作用。
5.实验结果5.1同步实验结果进程A开始执行进程A执行完毕进程B开始执行进程B执行完毕5.2互斥实验结果进程C开始执行进程C访问共享资源进程C执行完毕进程D开始执行进程D访问共享资源进程D执行完毕6.实验分析通过上述结果可以看出,同步实验中进程A和进程B按照正确的顺序执行,证明了同步机制的有效性。
互斥实验中进程C和进程D能够正确地交替访问共享资源,证明了互斥机制的有效性。
7.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。
同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。
在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。
进程同步与互斥总结进程同步与互斥,这可是操作系统里超级有趣又很重要的部分呢!咱们先来说说进程同步吧。
想象一下,进程就像是一群小伙伴,大家都在做自己的事情,但是有时候呢,这些小伙伴之间需要互相配合。
比如说,一个小伙伴负责生产东西,另一个小伙伴负责把生产出来的东西拿走。
那生产的小伙伴如果生产得太快,拿走的小伙伴还没来得及拿,就会出问题啦。
这时候就需要进程同步来协调他们。
进程同步就像是一个小指挥家,告诉每个进程什么时候该做什么事情,这样大家就能有条不紊地工作了。
那进程互斥又是什么呢?这就像是小伙伴们抢一个玩具一样。
比如说,有一个资源,就像那个玩具,很多进程都想要用。
但是这个资源一次只能被一个进程使用啊。
如果两个进程同时去用这个资源,那就乱套了,就像两个小伙伴同时抢一个玩具,可能会把玩具弄坏一样。
所以进程互斥就是要保证在某个时刻,只有一个进程能够访问这个特定的资源。
在实现进程同步和互斥的时候呢,有很多方法。
比如说信号量。
信号量就像是一个小信号灯。
如果信号灯是绿的,那就表示这个资源可以被使用,进程就可以进去做自己的事情。
如果信号灯是红的,那就表示这个资源已经被占用了,其他进程就得等着。
这就像我们过马路的时候,绿灯行,红灯停一样。
还有管程。
管程就像是一个小房子,里面有一些资源和一些管理这些资源的规则。
进程要使用这些资源,就得按照管程里的规则来。
这就好比是去一个特定的地方玩,那个地方有它自己的玩法,你得遵守才能玩得开心。
进程同步和互斥在很多地方都有应用呢。
就拿打印机来说吧。
很多人都可能想要用打印机打印东西,如果没有进程同步和互斥的管理,那就可能会出现混乱的情况。
可能一个文档打印到一半,另一个文档又开始打印了,那最后打印出来的东西就完全乱了。
在多线程编程的时候,进程同步和互斥也特别重要。
如果多个线程同时对一个共享变量进行操作,那结果可能就不是我们想要的了。
比如说,一个线程在给一个变量加1,另一个线程在给这个变量减1,如果没有协调好,那这个变量的值可能就变得乱七八糟的。
一、实验目的1. 理解进程同步的概念和原理;2. 掌握进程同步的基本方法和机制;3. 学会使用信号量实现进程同步;4. 通过实验验证进程同步机制的有效性。
二、实验原理1. 进程同步:在多道程序设计中,进程的执行是并发的,但某些情况下需要保证多个进程按照一定的顺序执行,以避免出现数据不一致、死锁等问题。
进程同步是指通过某种机制,协调多个进程的执行顺序,保证它们能够正确、有效地共享资源。
2. 信号量:信号量是一种特殊的变量,用于实现进程同步。
信号量具有两个原子操作:P操作(wait)和V操作(signal)。
P操作用于申请资源,V操作用于释放资源。
3. 互斥锁:互斥锁是一种常见的进程同步机制,用于保证临界资源的互斥访问。
当一个进程进入临界区时,它会尝试获取互斥锁,如果锁已被其他进程获取,则该进程进入等待状态;当进程退出临界区时,它会释放互斥锁。
三、实验内容1. 实验环境:Linux操作系统,C语言编程环境。
2. 实验工具:gcc编译器、gdb调试器。
3. 实验步骤:(1)创建一个互斥锁,用于保护临界资源。
(2)编写两个进程,分别模拟对临界资源的访问。
(3)在进程访问临界资源前,使用P操作尝试获取互斥锁。
(4)在进程访问临界资源后,使用V操作释放互斥锁。
(5)编译并运行程序,观察进程执行情况。
四、实验结果与分析1. 实验结果:(1)在互斥锁的保护下,两个进程能够按照预期顺序访问临界资源。
(2)当其中一个进程正在访问临界资源时,另一个进程会进入等待状态。
(3)当进程访问临界资源完成后,它会释放互斥锁,允许其他进程访问。
2. 实验分析:(1)互斥锁能够有效地保护临界资源,避免数据不一致问题。
(2)信号量P操作和V操作保证了进程的同步,避免了死锁现象。
(3)通过实验验证了进程同步机制的有效性。
五、实验总结本次实验通过使用信号量和互斥锁,实现了进程同步。
实验结果表明,信号量和互斥锁能够有效地保证进程按照预期顺序执行,避免数据不一致和死锁等问题。
操作系统实验进程同步与互斥操作系统实验进程同步与互斥实验目的1.掌握进程同步和互斥原理,理解生产者-消费者模型;2.学习Windows2000/xp中的多线程并发执行机制;3.学习使用Windows SDK解决读者-写者问题。
试验内容1依据生产者-消费者模型,在Windows 2000/xp环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥,分析、熟悉生产者消费者问题仿真的原理和实现技术。
(见附件2)试验内容2参考实验内容1和附件2伪码,编程解决读者-写者问题的程序。
(具体要求和读写者问题原始伪码内容见附件1)相关知识Windows 2000/XP的线程控制CreateThread完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。
ExitThread用于结束当前线程。
SuspendThread可挂起指定的线程。
ResumeThread可激活指定线程,它的对应操作是递减指定线程的挂起计数,当挂起计数减为0时,线程恢复执行。
Windows 2000/XP的进程互斥和同步在Windows 2000/XP中提供了临界区、互斥对象、信号量对象同步对象和相应的系统调用,用于进程和线程同步。
临界区对象(Critical Section)只能用于在同一进程内使用的临界区,同一进程内各线程对它的访问是互斥进行的。
相关API包括:InitializeCriticalSection对临界区对象进行初始化;EnterCriticalSection等待占用临界区的使用权,得到使用权时返回;TryEnterCriticalSection非等待方式申请临界区的使用权;申请失败时,返回0;LeaveCriticalSection释放临界区的使用权;DeleteCriticalSection释放与临界区对象相关的所有系统资源。
互斥对象(Mutex)互斥对象相当于互斥信号量,在一个时刻只能被一个线程使用。
实验四同步与互斥【实验目的和要求】1、掌握进程(线程)的同步与互斥。
2、掌握生产者消费者问题的实现方法。
3、掌握多线程编程方法。
【实验内容】实现生产者消费者问题1、有一个仓库,生产者负责生产产品,并放入仓库,消费者会从仓库中拿走产品(消费)。
2、仓库中每次只能入一个(生产者或消费者)。
3、仓库中可存放产品的数量最多10个,当仓库放满时,生产者不能再放入产品。
4、当仓库空时,消费者不能从中取出产品。
5、生产、消费速度不同。
【实验原理】1、信号量mutex提供对缓冲池访问的互斥要求并初始化为1,信号量empty和full分别用来表示空缓冲项和满缓冲项的个数,信号量empty初始化为n,信号量full初始化为0。
2、定义如下结构及数据:定义缓冲区内的数据类型:typedef int buffer_item;缓冲区:buffer_item buffer[BUFFER_SIZE];对缓冲区操作的变量:int in,out;信号量mutex提供了对缓冲池访问的互斥要求:pthread_mutex_t mutex;信号量empty和full分别表示空缓冲顶和满缓冲顶的个数:sem_t empty,full; 可以设定生产者的生产速度及消费者的消费速度:int pro_speed,con_speed;对缓冲区操作的自增函数:#define inc(k) if(k < BUFFER_SIZE) k = k+1;else k=03、并定义了如下实现问题的函数模块:将生产的产品放入缓冲区: int insert_item(buffer_item item)从缓冲区内移走一个产品: int remove_item(buffer_item *item)生产者进程:void *producer(void *param)消费者进程:void *consumer(void *param)生产者结构进程消费者结构进程【程序代码】//sx.c#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<semaphore.h>#include<time.h>#define inc(k) if(k<BUFFER_SIZE) k=k+1;else k=0#define BUFFER_SIZE 10//缓冲区的大小typedef int buffer_item;//定义缓冲区内的数据类型buffer_item buffer[BUFFER_SIZE];//缓冲区int in,out;//对缓冲区操作的变量pthread_mutex_t mutex;//信号量mutex提供了对缓冲池访问的互斥要求sem_t empty,full;//信号量empty和full分别表示空缓冲顶和满缓冲顶的个数int pro_speed,con_speed;//可以设定生产者的生产速度及消费者的消费速度int insert_item(buffer_item item){//将生产的产品放入缓冲区buffer[in]=item;printf("******insert缓冲池第%d号******\n",in);inc(in);}int remove_item(buffer_item *item){//从缓冲区内移走一个产品*item = buffer[out];printf("******remove缓冲池第%d号******\n",out);inc(out);}void *producer(void *param){//生产者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-pro_speed));printf("\n******第%d次生产******\n",++num);printf("******等待empty信号******\n");sem_wait(&empty);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备生产******\n");item = rand()%1000+1;printf("******生产产品%d*******\n",item);insert_item(item);printf("*******解锁******\n");printf("******第%d次生产结束*******\n\n",num); pthread_mutex_unlock(&mutex);sem_post(&full);}}void *consumer(void *param){//消费者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-con_speed));printf("\n******第%d次消费*****\n",++num); printf("******等待full信号******\n");sem_wait(&full);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备消费******\n"); remove_item(&item);pthread_mutex_unlock(&mutex);sem_post(&empty);printf("******消费产品%d*******\n",item);printf("*******解锁******\n");printf("******第%d次消费结束*******\n\n",num); }}int main()//主函数{pthread_t tid1,tid2;pthread_attr_t attr1,attr2;srand(time(NULL));pthread_mutex_init(&mutex,NULL);//初始化sem_init(&empty,0,BUFFER_SIZE);sem_init(&full,0,0);in=0;out=0;printf("***********************\n");printf("********开始!***********\n");printf("***********************\n");printf("生产者速度(1-15):\n");scanf("%d",&pro_speed);printf("消费者速度(1-15):\n");scanf("%d",&con_speed);pthread_attr_init(&attr1);pthread_create(&tid1,&attr1,producer,NULL);pthread_attr_init(&attr2);pthread_create(&tid2,&attr2,consumer,NULL);sleep(100);printf("*******程序over*******\n");return 0;}【实验步骤】编写程序代码gedit sx.c,再对代码进行编译gcc sx.c –o sx –lpthread,编译无错误,进行运行./sx,根据提示要求进行填写生产者和消费速度,观察消费者和生产者进程。
1.实验内容(进程的同步)(1)阅读理解示例程序。
(2)说明示例程序是否能适合解决N个生产者和1个消费者问题,并设计实验验证(3) 参照教材修改为N个生产者和1个消费者问题(4) 思考N个生产者和M个消费者问题的解决方案(不要求)(5) 利用信号量解决同步问题。
2.实验目的通过程序模拟及验证生产者消费者问题等经典问题,深入理解并发中的同步和互斥的概念3.实验原理(1)进程概念:(1.定义:程序的一次执行过程(2.三种基本状态:就绪状态,执行状态,阻塞状态(2)进程同步:(1.定义:并发进程在执行次序上的协调,以达到有效的资源共享和相互合作,使程序执行有可再现性。
(2.两种形式的制约关系:(一:资源共享关系:进程间接制约,需互斥地访问临界资源。
)、(二:相互合作关系:进程直接制约)(3.临界资源:一次仅允许一个进程访问的资源,引起不可再现性是因为临界资源没有互斥访问。
(3)信号量:定义一个用于表示资源数目的整型量S,它与一般的整型量不同,除初始化外,仅能通过两个标准的原子操作wait(S)和signal(S)来访问,俗称P,V操作。
通俗来讲就是用P来访问资源后减去一个单位资源,用V操作来释放一个单位资源就是现有资源上加一个单位资源。
4.实验内容一:说明示例程序是否能适合解决N个生产者和1个消费者问题,并设计实验验证答:示例程序不能解决多个生产者和消费者的问题,它是解决单个消费者和生产者的。
如果可以就要修改代码,如“二”所说。
二:多个消费者和生产者的问题如上图所示:如果要解决多个生产者和消费者的问题:第一步:分析上图得出了两种关系,分别是异步和同步的关系第二步:异步关系的是生产者和生产者之间的,因为同一时刻只能有一个生产者访问缓冲区,所以我们就可以设置临界资源.获得临界资源的生产者才能把产品放到缓冲区里第三步:同步关系有两个,首先是生产者和缓冲区之间,再是缓冲区和消费者之间。
他们都满足一前一后的关系,即当缓冲区空间未满时,生产者才可以放产品;缓冲区不为空的时候才可以让消费者取出产品消费。
线程互斥的实验报告线程互斥是操作系统中重要的概念之一。
在线程并发执行的情况下,多个线程可能会同时访问共享资源,如果没有互斥机制进行控制,就会出现数据竞争和不确定性的情况。
为了避免这种情况的发生,需要通过互斥机制对多个线程的并发访问进行合理控制。
二、实验目的本实验旨在通过编写程序,实现线程互斥的功能,进一步理解和掌握线程互斥的概念和原理,并验证互斥机制的有效性。
三、实验过程1. 创建共享资源:首先,我们创建一个共享资源,例如全局变量x。
2. 创建多个线程并发执行:通过创建多个线程来模拟多个并发执行的场景,每个线程都有访问共享资源的需求。
3. 创建互斥锁:使用操作系统提供的互斥锁实现机制来实现线程互斥,确保同时只有一个线程可以访问共享资源。
4. 设置互斥锁的加锁和解锁:在线程访问共享资源之前使用互斥锁进行加锁,在访问完共享资源之后进行解锁,以确保资源的正确性和完整性。
5. 运行程序并观察结果:运行多个线程并发执行的程序,通过打印输出等方式观察线程的执行情况,确保互斥机制的有效性。
四、实验结果与分析在实验过程中,我们创建了一个全局变量x作为共享资源,并创建了两个线程t1和t2来同时访问该变量。
通过使用互斥锁的机制,我们保证了同时只有一个线程可以访问变量x。
在线程t1对变量x进行操作之前,需要先获得互斥锁的加锁,操作完成后再进行解锁。
同样地,线程t2在操作变量x之前也需要获得互斥锁的加锁,操作完成后再进行解锁。
经过多次运行实验,观察到线程t1和t2的执行顺序是随机的,有时t1先执行,有时t2先执行。
这是因为线程的调度和执行是由操作系统决定的,而与我们代码编写的顺序无关。
但无论线程t1和t2的执行顺序如何,由于我们使用了互斥锁的机制,保证了对变量x的访问是互斥的,即同时只能有一个线程在操作变量x。
这也是我们对互斥机制的期望结果。
五、实验总结通过本实验,我们深入理解了线程互斥的概念和原理,并成功实现了线程互斥的功能。
操作系统实验报告——进程同步与互斥一、实验内容本实验主要内容是通过编写程序来实现进程的同步与互斥。
具体来说,是通过使用信号量来实现不同进程之间的同步和互斥。
我们将编写两个进程,一个进程负责打印奇数,另一个进程负责打印偶数,两个进程交替打印,要求打印的数字从1开始,直到100结束。
二、实验原理进程的同步是指多个进程之间按照一定的顺序执行,进程之间互相等待的关系。
而进程的互斥是指多个进程竞争同一个资源,需要通过其中一种方式来避免同时访问共享资源,以免造成数据错乱。
在本实验中,我们使用信号量来实现进程的同步与互斥。
信号量是一个计数器,用于表示一些共享资源的可用数量。
进程在访问共享资源时,需要先对信号量进行操作,当信号量大于0时,表示资源可用,进程可以访问;当信号量等于0时,表示资源不可用,进程需要等待。
进程同步的实现可以通过信号量的P操作与V操作来完成。
P操作用于申请资源,当资源可用时,将计数器减一,并进入临界区;V操作用于释放资源,当资源使用完毕时,将计数器加一,使等待资源的进程能够申请。
进程互斥的实现可以通过信号量的P操作与V操作结合临界区来完成。
当多个进程需要访问共享资源时,需要先进行P操作,进入临界区,访问完毕后进行V操作,离开临界区。
三、实验步骤1.首先,我们需要创建两个进程,一个进程负责打印奇数,另一个进程负责打印偶数。
2. 然后,我们创建一个共享变量count,用来记录打印的数字。
3. 接着,我们创建两个信号量odd和even,用来控制进程的同步与互斥。
odd信号量初始值为1,表示打印奇数的进程可以访问;even信号量初始值为0,表示打印偶数的进程需要等待。
4.编写奇数打印进程的代码,首先进行P操作,判断奇数信号量是否大于0,如果大于0,表示可以打印奇数。
5. 如果可以打印奇数,将count加一,并输出当前的奇数,然后进行V操作,释放偶数打印进程的等待。
6.同样的,编写偶数打印进程的代码,首先进行P操作,判断偶数信号量是否大于0,如果大于0,表示可以打印偶数。
操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期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; //线程IDint 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';elsethread_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);//创建消费者线程elsehThreads[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、记录生产者和消费者的同步执行过程。