进程(线程)的同步与互斥实验报告
进程(线程)同步和互斥实验报告
进程(线程)同步和互斥实验报告操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期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编程实现进程同步和互斥进程(线程)同步和互斥是操作系统中非常重要的概念,它们用于控制多个进程(线程)之间的访问顺序,以确保数据的一致性和正确性。
在本文中,我们将详细介绍进程(线程)同步和互斥的概念,并通过编程实现来说明它们的具体应用。
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)互斥对象相当于互斥信号量,在一个时刻只能被一个线程使用。
实验四同步与互斥Linux实验报告
实验四同步与互斥【实验目的和要求】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,表示可以打印偶数。
进程同步:实验报告
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、进一步认识并发执行的实质2、分析进程竞争资源的现象,学习解决进程同步互斥的方法实验内容1、编写程序,使用相关函数实现父子进程对共享文件的同步互斥访问。
2、修改程序,观察对临界资源访问的互斥控制的作用。
实验基础一、临界资源的互斥访问。
为了实现多进程对临界资源的互斥访问,一个进程访问临界资源的典型程序段类似如下形式:进入区临界区;退出区其余代码;其中,进入区中判断资源是否可用,如果可用,则资源数量减1,进程进入临界区;否则进程阻塞等待。
退出区中资源数量加1,唤醒阻塞等待该资源的进程。
进入区和退出区都是原子操作。
操作系统中,通常用信号量来实现进入区和退出区,即P操作和V操作。
为了实现用户程序中对某些资源的同步互斥访问,操作系统也提供了一些函数接口,功能类似于对特定临界区的进入区和退出区功能。
二、相关的系统调用。
e):用作锁定文件的某些段或者整个文件。
函数原型:#include intlockf(intfiles,intfunction;longsize)其中:files是文件描述符;参数function可以取以下值:F_LOCK:锁定一个区域。
F_ULOCK:解除锁定。
参数size指明了从文件当前位置开始的一段连续锁定区域的长度,当size为0时,锁定记录将由当前位置一直扩展到文件尾。
如果lockf的参数function 取值为F_LOCK,而指定文件的对应区域已被其他进程锁定,那么lockf的调用进程将被阻塞直到该区域解锁。
通过使用lockf函数,可实现多进程对共享文件进行互斥访问。
进程的实现中,必须使得每个进程在使用文件前对文件加锁,使用文件后解锁。
(22)openopen:打开一个文件:打开一个文件函数原型:#include#include#includeintopen(char*path,intflags,mode_tmode);其中:参数path是指向所要打开的文件的路径名指针。
进程互斥实验报告
一、实验目的1. 理解进程互斥的概念和意义。
2. 掌握进程互斥的实现方法。
3. 熟练运用信号量机制解决进程互斥问题。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 2019三、实验内容1. 进程互斥的概念进程互斥是指两个或多个进程不能同时进入关于同一组共享变量的临界区域。
如果多个进程同时访问临界资源,可能会导致数据不一致或程序错误。
因此,进程互斥是操作系统中的一个重要概念。
2. 进程互斥的实现方法(1)软件方法:通过程序设计实现进程互斥,如使用锁(Lock)机制、信号量(Semaphore)机制等。
(2)硬件方法:利用处理器提供的特殊指令实现进程互斥,如Test-and-Set指令。
3. 信号量机制信号量是一种整数变量,用于实现进程同步和互斥。
信号量有三种操作:P操作(等待)、V操作(信号)和初始化。
(1)P操作:当进程需要访问临界资源时,先执行P操作。
如果信号量的值大于0,则将其减1,进程继续执行;如果信号量的值等于0,则进程进入阻塞状态,等待其他进程释放信号量。
(2)V操作:当进程访问完临界资源后,执行V操作。
如果此时有其他进程因P操作而阻塞,则将其唤醒,继续执行。
(3)初始化:将信号量的值设置为1,表示临界资源可用。
4. 实验步骤(1)创建一个信号量对象。
(2)在访问临界资源前,执行P操作。
(3)访问临界资源。
(4)访问完成后,执行V操作。
(5)重复步骤(2)至(4)。
5. 实验程序以下是一个使用信号量实现进程互斥的示例程序:```cpp#include <iostream>#include <thread>#include <semaphore.h>// 创建信号量sem_t sem;// 访问临界资源的函数void accessResource() {// 执行P操作sem_wait(&sem);// 访问临界资源std::cout << "进程 " << std::this_thread::get_id() << " 正在访问临界资源" << std::endl;// 执行V操作sem_post(&sem);}int main() {// 初始化信号量sem_init(&sem, 0, 1);// 创建多个线程std::thread t1(accessResource);std::thread t2(accessResource);std::thread t3(accessResource);// 等待线程结束t1.join();t2.join();t3.join();// 销毁信号量sem_destroy(&sem);return 0;}```6. 实验结果与分析通过运行实验程序,可以观察到多个线程交替访问临界资源,实现了进程互斥。
进程同步实验报告
实验三进程的同步一、实验目的1、了解进程同步和互斥的概念及实现方法;2、更深一步的了解fork()的系统调用方式。
二、实验内容1、预习操作系统进程同步的概念及实现方法。
2、编写一段源程序,用系统调用fork()创建两个子进程,当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。
程序的输出是什么?分析原因。
3、阅读模拟火车站售票系统和实现进程的管道通信源代码,查阅有关进程创建、进程互斥、进程同步的系统功能调用或API,简要解释例程中用到的系统功能或API的用法,并编辑、编译、运行程序,记录程序的运行结果,尝试给出合理的解释。
4、(选做)修改问题2的代码,使得父子按顺序显示字符“a”;“b”、“c”编辑、编译、运行。
记录程序运行结果。
三、设计思想1、程序框架(1)创建两个子进程:(2)售票系统:(3)管道通信:先创建子进程,然后对内容加锁,将输出语句存入缓存,并让子进程自己进入睡眠,等待别的进程将其唤醒,最后解锁;第二个子进程也执行这样的过程。
父进程等待子进程后读内容并输出。
(4)修改程序(1):在子进程的输出语句前加上sleep()语句,即等待父进程执行完以后再输出。
2、用到的文件系统调用函数(1)创建两个子进程:fork()(2)售票系统:DWORD WINAPI Fun1Proc(LPVOID lpPartameter);CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);CloseHandle(hThread1);(HANDLE)CreateMutex(NULL,FALSE,NULL);Sleep(4000)(sleep调用进程进入睡眠状态(封锁), 直到被唤醒);WaitForSingleObject(hMutex,INFINITE);ReleaseMutex(hMutex);(3)管道通信:pipe(fd),fd: int fd[2],其中: fd[0] 、fd[1]文件描述符(读、写);lockf( fd,function,byte)(fd: 文件描述符;function: 1: 锁定 0:解锁;byte: 锁定的字节数,0: 从当前位置到文件尾);write(fd,buf,byte)、read(fd,buf,byte) (fd: 文件描述符;buf : 信息传送的源(目标)地址;byte: 传送的字节数);sleep(5);exit(0);read(fd[0],s,50)(4)修改程序(1):fork(); sleep();四、调试过程1、测试数据设计(1)创建两个子进程:运行结果:(2)售票系统:运行结果:(3)管道通信:运行结果:(4)修改程序(1):2、测试结果分析 (1)调用fork()创建一个子进程,当运行到第一个子进程输出了b ,当父进程运行时创建另一个子进程。
实验四-同步与互斥-Linux实验报告
实验四-同步与互斥-Linux实验报告实验四同步与互斥 Linux 实验报告一、实验目的本次实验旨在深入理解操作系统中进程的同步与互斥概念,通过在Linux 环境下进行编程实践,掌握相关的实现方法和技术,提高对并发控制的认识和应用能力。
二、实验环境操作系统:Linux(Ubuntu 2004)编程语言:C 语言开发工具:GCC 编译器三、实验原理(一)同步同步是指多个进程在执行过程中需要按照一定的顺序协调工作,以确保它们之间的操作具有正确的逻辑关系。
常见的同步机制包括信号量、条件变量等。
(二)互斥互斥是指在同一时刻,只允许一个进程访问共享资源,以避免多个进程同时操作导致的数据不一致或错误。
实现互斥的常见方法有互斥锁、临界区等。
四、实验内容(一)使用信号量实现生产者消费者问题1、问题描述生产者不断生产产品并放入缓冲区,消费者从缓冲区取出产品进行消费。
缓冲区大小有限,当缓冲区满时生产者停止生产,当缓冲区为空时消费者停止消费。
2、实现思路创建一个信号量来表示缓冲区的可用空间数量,另一个信号量表示缓冲区中已有的产品数量。
生产者在生产前检查可用空间信号量,消费者在消费前检查产品数量信号量。
3、代码实现```cinclude <stdioh>include <stdlibh>include <pthreadh>include <semaphoreh>define BUFFER_SIZE 5int bufferBUFFER_SIZE;int in = 0;int out = 0;sem_t empty_sem;sem_t full_sem;pthread_mutex_t mutex;void producer(void arg) {int item;while (1) {item = rand()% 100;sem_wait(&empty_sem);pthread_mutex_lock(&mutex);bufferin = item;printf("Producer: Produced item %d at position %d\n", item, in);in =(in + 1) % BUFFER_SIZE;pthread_mutex_unlock(&mutex);sem_post(&full_sem);}return NULL;}void consumer(void arg) {int item;while (1) {sem_wait(&full_sem);pthread_mutex_lock(&mutex);item = bufferout;printf("Consumer: Consumed item %d from position %d\n", item, out);out =(out + 1) % BUFFER_SIZE;pthread_mutex_unlock(&mutex);sem_post(&empty_sem);}return NULL;}int main(){pthread_t producer_thread, consumer_thread;sem_init(&empty_sem, 0, BUFFER_SIZE);sem_init(&full_sem, 0, 0);pthread_mutex_init(&mutex, NULL);pthread_create(&producer_thread, NULL, producer, NULL);pthread_create(&consumer_thread, NULL, consumer, NULL);pthread_join(producer_thread, NULL);pthread_join(consumer_thread, NULL);sem_destroy(&empty_sem);sem_destroy(&full_sem);pthread_mutex_destroy(&mutex);return 0;}```(二)使用互斥锁实现读者写者问题1、问题描述存在多个读者和一个写者,读者可以同时读取数据,但写者在写数据时不允许有其他读者或写者访问。
操作系统实验报告——进程同步与互斥
《进程同步与互斥》实验报告实验序号:01 实验项目名称:进程同步与互斥学号姓名专业、班实验地点指导教师时间一、实验目的1、掌握基本的进程同步与互斥算法,理解生产者-消费者问题。
2、学习使用Windows 2000/XP中基本的同步对象,掌握相关API的使用方法。
3、了解Windows 2000/XP中多线程的并发执行机制,实现进程的同步与互斥。
4、设计程序,实现生产者-消费者进程(线程)的同步与互斥;二、实验环境Windows 2000/XP + Visual C++ 6.0三、实验内容以生产者-消费者模型为依据,在Windows 2000/XP环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
四、设计思路和流程框图生产者进程的功能:生产东西,供消费者消费;消费者进程的功能:消费生产者生产的东西。
生产者生产产品并存入缓冲区供消费者取走使用,消费者从缓冲器内取出产品去消费。
在生产者和消费者同时工作时,必须禁止生产者将产品放入已装满的缓冲器内,禁止消费者从空缓冲器内取产品。
五、源程序(含注释)清单#include<windows.h>printf("Consumer %2d finish consuming product %2d\n ",m_serial,m_thread_request[i]);}//离开临界区LeaveCriticalSection(&PC_Critical[BufferPos]);}}六、测试结果以及实验总结1、通过实验进一步了解了基本的进程同步与互斥算法,理解生产者-消费者问题2、掌握了相关API的使用方法。
3、了解到进程是一个可以拥有资源的基本单位,是一个可以独立调度和分派的基本单位。
而线程是进程中的一个实体,是被系统独立调度和分配的基本单位,故又称为轻权(轻型)进程(Light Weight Process)。
线程的同步和互斥问题
实验二线程的同步和互斥问题一.实验内容:编写程序实现并发线程之间的同步和互斥问题。
线程间的互斥:并发执行的线程共享某些类临界资源,对临界资源的访问应当采取互斥的机制。
线程间的同步:并发执行的线程间通常存在相互制约的关系,线程必须遵循一定的规则来执行,同步机制可以协调相互制约的关系。
二.实验目的和要求1)了解进程同步与互斥的概念,掌握编写进程同步、互斥的实例。
2)解决一类典型的进程间同步问题,如生产者-消费者问题,读者-写者问题等。
三.实验方法和步骤1.实验方法掌握同步与互斥的机制,选取合适的问题,给出演示程序的设计思想,包括流程图的形式;选取C、C++、VC、JA V A等计算机语言,编程调试,最终给出运行正确的程序。
2.程序设计(1)线程间互斥:分析问题,创建多个线程,找出临界资源,划出正确的临界区,根据互斥机制的操作模式,编写程序。
互斥机制的操作模式:p(mutex);/*关锁*/临界区的操作;v(mutex);/*开锁*/(2)线程间同步——读者-写者问题示例:在Windows 2000 环境下,创建一个包含n 个线程的控制台进程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件的要求,进行读写操作。
请用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制:1)写-写互斥;2)读-写互斥;3)读-读允许;运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。
测试数据文件格式测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,各字段间用空格分隔。
第一字段为一个正整数,表示线程序号。
第二字段表示相应线程角色,R 表示读者是,W 表示写者。
第三字段为一个正数,表示读写操作的开始时间。
操作系统进程同步和互斥的实验报告
湖南农业大学信息科学技术学院学生实验报告【实验步骤、过程】(含原理图、流程图、关键代码,或实验过程中的记录、数据等)生产者进程(进程由多个线程组成)生产信息,例如它可以是计算进程。
消费者进程使用信息,它可以是输岀打印进程。
由于生产者和消费者彼此独立,且运行速度不确定,所以很可能岀现生产者已产生了信息而消费者却没有来得及接受信息这种情况。
为此,需要引入由一个或者若干个存储单元组成的临时存储区,以便存放生产者所产生的信息,平滑进程间由于速度不确定所带来的问题。
这个临时存储区叫做缓冲区,通常用一维数组来表示。
由一个或若干个存储单元组成的缓冲区叫作“有穷缓冲区”。
下面我们来分析一下有穷缓冲的生产者和消费者的例子。
原理图假设有多个生产者和多个消费者,它们共享一个具有n个存储单元的有穷缓冲区Buffer(O .... n -1),这是一个环形队列。
其队尾指针Rear指向当前信息应存放的位置(Buffer[Rear]),队首指针Front指向当前取出信息的位置(Buffer[front])。
生产者进程总是把信息存放在Buffer[Rear]中,消费者进程则总是从Buffer [Rear] 中取出信息。
如果想使生产者进程和消费者进程协调合作,则必须使它们遵循如下规则:1)只要缓冲区有存储单元,生产者都可往其中存放信息;当缓冲区已满时,若任意生产者提岀写要求,则都必须等待;2)只要缓冲区中有消息可取,消费者都可从缓冲区中取岀消息;当缓冲区为空时,若任意消费者想取岀信息,则必须等待;3)生产者们和消费者们不能同时读、写缓冲区。
流程图代码:public class ProducerC on sumer { public static void main( Str in g[] args) { Syn cStack ss = new Syn cStack(); Producer p = new Producer(ss);Con sumer c = new Con sumer(ss); new Thread(p).start();new Thread(p).start();new Thread(p).start();new Thread(c).start();}}class WoTou {int id;WoTou(i nt id) {=id;}public Stri ng toStri ng() {return "WoTou :" + id;}}class Syn cStack {int in dex = 0;WoTo u[] arrWT = new WoTou[6];public syn chr oni zed void push(WoTou wt) { while(i ndex == {try {();} catch (In terruptedExcepti on e) {();}}();arrWT[i ndex] = wt;in dex ++;}public syn chr oni zed WoTou pop() { while(i ndex == 0) {try {();} catch (In terruptedExcepti on e) {();}}();in dex--;retur n arrWT[i ndex];}}class Producer impleme nts Runn able { Syn cStack ss = n ull;Producers yn cStack ss) {=ss;}public void run() {for(i nt i=0; i<20; i++) {WoTou wt = new WoTou(i);(wt);"生产了:“ + wt);try {((in t)() * 200));} catch (In terruptedExcepti on e) {();}}}}class Con sumer impleme nts Runn able { Syn cStack ss = n ull;Con sumer(S yn cStack ss) {=ss;}public void run() {for(i nt i=0; i<20; i++) {WoTou wt =();"消费了:" + wt);try {((in t)() * 1000));} catch (In terruptedExcepti on e) {();}}}}结果:(随机的)生产了:WoTou : 0生产了:WoTou : 0 消费了:WoTou:0生产了:WoTou: 1 生产了:WoTou: 1 生产了:WoTou: 1 生产了:WoTou:2 生产了:WoTou : 3 消费了:WoTou : 2 消费了:WoTou:3生产了:WoTou : 4 消费了:WoTou : 4 生产了:WoTou:5 消费了:WoTou:5生产了:WoTou : 6 消费了:WoTou : 6 生产了:WoTou:2 消费了:WoTou:2生产了:WoTou : 3 消费了:WoTou : 3 生产了:WoTou:4 消费了:WoTou:4生产了:WoTou : 5 消费了:WoTou : 5 生产了:WoTou:6消费了:WoTou:6【实验结果或总结】(对实验结果进行相应分析,或总结实验的心得体会,并提出实验的改进意见)【备注】。
操作系统进程同步与互斥实验报告0204192337
学生实验报告姓名:年级专业班级学号成绩#define N 1 //N定义为临界资源!printf("请输入三个进程:\n"); //初始状态为:临界资源处于空闲状态!loop:scanf("%d %d %d",&a,&b,&c); //输入的进程名为:a,b,c!进程名输入的先后代表进程的访问顺序!if(a==N) //判断进程a是否占据临界资源!若a==N,表明a访问临界资源!{printf("a=%d\n",a); //a正在访问临界资源!printf("b=0,c=0\n"); //b,c不能进入自己的临界区,需等待a释放临界资源!printf(“临界资源正在被进程a访问,进程b,c必须等待.\n”);}else if(b==N){printf("b=%d\n",b); //b正在访问临界资源!printf("a=0,c=0\n"); //a,c不能进入自己的临界区,需等待b释放临界资源!printf(“临界资源正在被进程b访问,进程a,c必须等待.\n”);}5.编译链接所编写的程序,在编译正确的情况下执行程序.6.记录程序执行的结果(如下图所示).注意:初始状态为:临界资源处于空闲状20 10年12 月16 日【实验结果或总结】(对实验结果进行相应分析,或总结实验的心得体会,并提出实验的改进意见)1.进程a,b,c分别访问临界资源时程序执行的结果如下.(a) (b) (c)2.该程序初始化N为临界资源,根据输入a,b,c,的值是否等于N来判断进程分别是否进入自己的临界区。
当a=N 表明进程a正在访问临界资源。
此时程序执行的输出为:a=1,b=c=0表示进程b,c不能进入自己的临界区。
3.该程序能较好地体现程序并发执行时的一种制约关系-互斥,但不能较好的反映进程的同步关系,所以该算法有待改进,用以同时实现进程的同步和互斥。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期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、记录生产者和消费者的同步执行过程。