操作系统线程同步机制实验报告

合集下载

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

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

进程(线程)同步和互斥实验报告操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期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、实验目的在掌握基于消息的windows程序结构和多线程程序设计方法的基础上,设计一个多线程同步的程序。

使学生能够从程序设计的角度了解多线程程序设计的方法和在windows系统下多线程同步互斥的机制。

2、实验内容理解Windows程序设计的基本思想,理解基于消息的程序设计方法,能够设计出简单的基于事件的windows程序,完成基本控件的使用结合操作系统中信号量与互斥体的概念,在MFC中找到对应的相关类。

设计一个多线程同步的程序。

二、实验方案1、定义相关的信息,创建生产者和消费者线程。

设定生产和消费的规则,初步设定没生产两个产品就将其中一个取出消费。

2、设定一个循环队列,作为缓冲区,设计生产者消费者算法。

3、使用互斥的思路,当缓冲区满时迫使生产者等待,当缓冲区空时迫使消费者等待。

4、源代码#include <windows.h>#include <iostream>using namespace std;unsigned short ProductID = 0,ConsumeID = 0,in = 0,out = 0;const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列bool g_continue = true; //控制程序结束HANDLE g_hMutex; //用于线程间的互斥HANDLE g_hFullSemaphore;HANDLE g_hEmptySemaphore;DWORD WINAPI Producer(LPVOID); //生产者线程DWORD WINAPI Consumer(LPVOID); //消费者线程const unsigned short PRODUCERS_COUNT = 2; //生产者的个数const unsigned short CONSUMERS_COUNT = 1; //消费者的个数const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT; HANDLE hThreads[PRODUCERS_COUNT]; //各线程的handleDWORD producerID[CONSUMERS_COUNT]; //生产者线程的标识符DWORD consumerID[THREADS_COUNT]; //消费者线程的标识符void Produce(){ cout << "正在生产第 " << ++ProductID << " 号产品 "; cout << "生产成功" << endl;}void Append(){ cout<< "存放新产品 ";g_buffer[in] = ProductID;in = (in+1)%SIZE_OF_BUFFER;cout<< "成功" << endl;cout<<"缓冲区情况"<<endl;for (int i=0;i<SIZE_OF_BUFFER;++i){cout << i <<": " << g_buffer[i];if (i==in) cout << " <-- 生产";if (i==out) cout << " <-- 消费";cout << endl;} cout<<endl;}void Take(){ cout<< "取出一个产品 ";ConsumeID = g_buffer[out];out = (out+1)%SIZE_OF_BUFFER;cout<< "成功" << endl;for (int i=0;i<SIZE_OF_BUFFER;++i){cout << i <<": " << g_buffer[i];if (i==in) cout << " <-- 生产";if (i==out) cout << " <-- 消费";cout << endl;}cout<<endl;}void Consume(){ cout<< "消费第 " << ConsumeID << " 号产品";cout<< "成功" << endl;}DWORD WINAPI Producer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hFullSemaphore,INFINITE); WaitForSingleObject(g_hMutex,INFINITE);Produce();Append();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);} return 0;}DWORD WINAPI Consumer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hEmptySemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Take();Consume();Sleep(2000);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hFullSemaphore,1,NULL); }return 0;}int main(){ //创建各个互斥信号g_hMutex = CreateMutex(NULL,FALSE,NULL);g_hFullSemaphore= CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1, NULL);g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);//创建生产者线程for (int i=0;i<PRODUCERS_COUNT;++i){hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if (hThreads[i]==NULL) return -1; }//创建消费者线程for(i=0;i<CONSUMERS_COUNT;++i){ hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0, Consumer,NULL,0,&consumerID[i]);if (hThreads[i]==NULL){ return -1; }while(g_continue){ if(getchar()){ g_continue = false; }//按回车后终止程序运行}return 0;}}三、实验数据、结果分析运行结果四、总结。

操作系统实验线程同步

操作系统实验线程同步

实验2:线程同步一、实验目的(1)掌握Windows2000环境下,线程同步。

(2)熟悉Windows2000提供的线程同步与互斥API。

(3)用Windows2000提供的线程同步与互斥API解决实际问题(producer-consumer)。

二、实验内容生产者与消费者问题的实现。

在Windows 2000环境下,创建一组“生产者”线程和一组“消费者”线程,并建立一个长度为N的全局数组作为共享缓冲区。

“生产者”向缓冲区输入数据,“消费者”从缓冲区读出数据。

当缓冲区满时,“生产者”必须阻塞,等待“消费者”取走缓冲区数据后将其唤醒。

当缓冲区空时,“消费者”阻塞,等待“生产者”生产了产品后将其唤醒。

试用信号量实现“生产者”与“消费者”线程之间的同步。

三、实验环境(1)使用的操作系统及版本。

Windows xp professional(2)使用的编译系统及版本。

Visual c++ 6.0四、实验步骤1.等待一个对象(相当于p操作)WaitForSingleObject用于等待一个对象。

它等待的对象可以为:Change notification:变化通知。

Console input:控制台输入。

Event:事件。

Job:作业。

Mutex:互斥信号量。

Process:进程。

Semaphore:计数信号量。

Thread:线程。

Waitable timer:定时器。

返回值:如果成功返回,其返回值说明是何种事件导致函数返回。

访问描述WAIT_ABANDONED 等待的对象是一个互斥(mutex)对象,该互斥对象没有被拥有它的线程释放,它被设置为不能被唤醒。

WAIT_OBJECT_0 指定对象被唤醒。

WAIT_TIMEOUT 超时。

2.创建信号量CreateSemaphore用于创建一个信号量。

返回值:信号量创建成功,将返回该信号量的句柄。

如果给出的信号量名是系统已经存在的信号量,将返回这个已存在信号量的句柄。

操作系统线程同步机制实验报告

操作系统线程同步机制实验报告

操作系统线程同步机制实验报告一、实验名称:线程同步机制二、实验内容及目的:2.1、通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性;2.2、利用现有操作系统提供的同步机制编程实现两线程的有序控制;2.3、根据同步机制的Peterson软件解决方案编程实现同步机制对于同一问题的解决;2。

4、基于程序运行时间长短比较两种同步机制。

三、实验步骤:3.1、编程实现不设置任何线程同步机制的多线程银行转账程序,观察输出结果。

3。

1。

1、主要代码(完整代码见附录)://nAccount1与nAccount2为全局变量,也是此线程同步机制里的临界变量.do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;} while ((nAccount1 + nAccount2) == 0);3.1.2、输出结果:当没有任何线程同步机制时,程序循环不了多少次便跳了出来,某一次的输出结果如下图:图一无线程同步机制时的程序运行结果3.2、编程实现调用系统Mutex的多线程银行转账程序,观察输出结果。

3。

2.1、:主要代码(完整代码见附录):do{::WaitForSingleObject(m1,INFINITE);nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;if((nAccount1 + nAccount2) != 0)break;::ReleaseMutex(m1);nLoop++;} while (nLoop 〈= 1000000);为了防止程序陷入死循环,在while条件里加上了nloop〈=1000000,当循环执行到第1000001时将跳出。

操作系统线程同步实验报告

操作系统线程同步实验报告

线程同步实验报告
实验目的:讨论临界区问题及其解决方案。

实验内容:首先创建两个共享数据资源的并发进程,然后分别在没有同步控制机制、采用mutex机制以及使用软件方法(Peterson)的情况下探究并尽量解决所产生的异常情况。

实验结果:(一)结果截图
1、没有同步控制机制
2、使用mutex机制(其中run1、run2是标志进程输出次数)
3、Peterson算法
(二)结果分析
按照输出结果的稳定性来评判一个程序的好坏,那么大体可以总结为:没有使用同步控制机制<mutex机制<软件机制。

mutex机制是实现由一个进程对公共资源进行访问的时候,不允许其它进程对此资源进行访问。

保证了进程之间的互斥性。

软件机制是使用Peterson算法实现进程间的轮流进行以及进程之间的互斥性。

但是实验结果显示每一种方法均存在异常情况,即在一定次数后程序结束。

产生异常的原因大致分为以下几种:1、进程间的相互影响导致在访问同一个共同资源时会出现变量值与理论值产生偏差,使得不满足循环条件;2、针对单处理机的程序在处理多处理机的问题上会出现偏差;3、PC机本身内存可能存在的部分遗留的数据会影响数据的运算。

操作系统线程的同步

操作系统线程的同步
else if(dRes==WAIT_ABANDONED) printf("WAIT_ABANDONED!dRes=%d\n",dRes);
elseprintf("dRes=%d\n",dRes);
CloseHandle(h1);
CloseHandle(hHandle1);
ExitThread(0);
《操作系统原理》实验报告
实验序号:5实验项目名称:线程的同步
学 号
姓 名专业Biblioteka 级实验地点指导教师
实验时间
一、实验目的及要求
1.进一步掌握Windows系统环境下线程的创建与撤销。
2.熟悉Windows系统提供的线程同步API。
3.使用Windows系统提供的线程同步API解决实际问题。
二、实验设备(环境)及要求
if (h1==NULL) printf("Thread1 create Fail!\n");
else printf("Thread1 create Success!\n");
dRes=WaitForSingleObject(hHandle1,INFINITE); //主线程等待子线程结束
err=GetLastError();
<参考程序>
//#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
static HANDLE h1; //线程句柄
static HANDLE hHandle1=NULL; //信号量句柄
void func();
int main(int argc, char* argv[])

操作系统实验报告—Windows线程同步机制

操作系统实验报告—Windows线程同步机制

2012-2013学年第一学期计算机操作系统实验报告专业:班级:学号:姓名:提交日期:Windows线程同步机制【开发语言及实现平台或实验环境】C++/C#Microsoft Visual Studio 6.0/ Microsoft Visual Studio .NET【实验目的】(1) 了解Windows线程同步机制;(2) 了解互斥体,并通过查阅资料理解互斥体对象的使用方法;(3) 了解事件,并通过查阅资料理解事件对象的使用方法;(4) 了解关键区,并通过查阅资料理解关键区对象的使用方法;(5) 了解信号量,并通过查阅资料理解信号量对象的使用方法;(6) 利用Windows线程同步机制,模拟生产者消费者问题。

【实验要求】(1) 逐程序进行简要分析、运行各程序并仔细阅读注释;(2) 查阅MSDN或其他资料,掌握相关系统调用使用方法和参数含义;(3) 完成实验报告。

【实验步骤】(1) 阅读和理解2-1(mutex).cpp文件中的程序,运行2-1(mutex).cpp,认真观察结果。

然后将两个子函数中注释掉的Sleep语句让其可用,再多次运行,认真观察结果,不会出现销售异常情况。

比较修改程序前后运行结果发生的变化,并分析其原因。

(2) 2-2(event).cpp、2-3(critical_section).cpp的处理方式同(1)。

(3) 阅读和理解2-4(Producer_Consumer).cpp文件中的程序,运行2-4(Producer_Consumer).cpp,认真观察结果,先生产后消费。

然后将两个子函数中注释掉的while语句让其可用,再多次运行,认真观察结果,生产者和消费者保持同步。

比较修改程序前后运行结果发生的变化,并分析其原因。

(4) 阅读和理解2-4(Producer_Consumer)1.cpp文件中的程序,运行2-4(Producer_Consumer)1.cpp,认真观察结果。

实验三 操作系统中的线程同步

实验三  操作系统中的线程同步

实验三操作系统中的线程同步一、实验目的1、加深对线程的理解、掌握Windows中线程的操作。

2、掌握信号量、互斥量、事件、临界区等同步对象的使用。

二、实验理论基础及教材对应关系1、进程和线程的关系。

2、线程间的同步和通信。

3、本实验内容主要对应于教材第2章中关于线程的各节、第3章中关于死锁的各节。

三、实验内容与步骤1、定义全局变量int i = 0; 初始值置为0。

2、创建两个线程,一个对i 执行加1 操作,另一个对i 执行减1 操作。

两个线程执行相同的次数。

显然,正常情况下,i 的仍然保持为0。

#include <stdio.h>#include <windows.h>#define MaxCount 9000000 // 循环次数要很大,可多次尝试一些值DWORD __stdcall fun1( LPVOID p1){for( int j =0 ;j < MaxCount;j++){i++;}return 0;}DWORD __stdcall fun2( LPVOID p1){for( int j =0 ;j < MaxCount;j++){i--;}return 0;}3、观察两个线程执行后的情况,可以发觉最后i 的值不一定是0,有时是很大的正数,有时是很大的负数,这就是多个线程在操作同一个变量i时,未同步时带来的严重问题。

还应该了解,在多个线程操作共享的变量时,才需要考虑同步问题。

1、给这两个线程加上同步代码,再来观察对 i 值的影响。

步骤2的函数稍微改动即可:CRITICAL_SECTION cs;DWORD __stdcall fun1( LPVOID p1){for( int j =0 ;j < MaxCount;j++){::EnterCriticalSection(&cs);i++;::LeaveCriticalSection(&cs);}}DWORD __stdcall fun2( LPVOID p1){for( int j =0 ;j < MaxCount;j++){::EnterCriticalSection(&cs);i--;::LeaveCriticalSection(&cs);}}加入的同步代码的两个线程,无论如何执行,i 的值总是 0 ,结果是正确的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

操作系统线程同步机制实验报告一、实验名称:线程同步机制二、实验内容及目的:2.1、通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性;2.2、利用现有操作系统提供的同步机制编程实现两线程的有序控制;2.3、根据同步机制的Peterson软件解决方案编程实现同步机制对于同一问题的解决;2.4、基于程序运行时间长短比较两种同步机制。

三、实验步骤:3.1、编程实现不设置任何线程同步机制的多线程银行转账程序,观察输出结果。

3.1.1、主要代码(完整代码见附录)://nAccount1与nAccount2为全局变量,也是此线程同步机制里的临界变量。

do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;} while ((nAccount1 + nAccount2) == 0);3.1.2、输出结果:当没有任何线程同步机制时,程序循环不了多少次便跳了出来,某一次的输出结果如下图:图一无线程同步机制时的程序运行结果3.2、编程实现调用系统Mutex的多线程银行转账程序,观察输出结果。

3.2.1、:主要代码(完整代码见附录):do{::WaitForSingleObject(m1,INFINITE);nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;if((nAccount1 + nAccount2) != 0)break;::ReleaseMutex(m1);nLoop++;} while (nLoop <= 1000000);为了防止程序陷入死循环,在while条件里加上了nloop<=1000000,当循环执行到第1000001时将跳出。

3.2.2、输出结果:调用Mutex时的程序运行结果如图二:图二调用Mutex时的程序运行结果3.3、编程实现利用Peterson算法,实现线程同步的多线程银行转账程序,观察输出结果:3.3.1、主要代码(完整代码见附录):do{flagi = true;turn = j;while(flagj && turn == j);nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;if((nAccount1 + nAccount2) != 0)break;flagi = false;nLoop++;} while (nLoop <= 1000000);为了防止程序陷入死循环,在while条件里加上了nloop<=1000000,当循环执行到第1000001时将跳出。

3.3.2、输出结果:使用Peterson法时的输出结果如图三:图三使用Peterson算法时的输出结果3.4、对以上三步所得结果的分析:3.4.1、由步骤1可知不采取任何线程同步措施的多线程银行转账程序执行不了多少次就会出问题。

其原因在于共享资源nAccount1和nAccount2没有实现互斥访问,当两线程同时对其修改,导致数据不一致时,将跳出循环。

3.4.2、比较步骤2与步骤3的结果,可知:实现的线程同步时,用Peterson 法的效率要比调用系统Mutex互斥变量的效率高很多。

循环1000000次的时间,前者仅为26ms,而后者需4917ms。

其原因在于Peterson法只用一些本地变量来实现,这个存取速度是相当快的,而调用系统Mutex互斥变量涉及到好几个Windows API(应用程序编程接口)的调用,必然比较慢。

四、实验心得:通过这次实验,体会到线程同步机制的重要性,同时,在选用线程同步机制时也应该根据具体案例的要求选择合适的线程同步机制,对效率要求很高的程序就应该自己编写效率比较高的线程同步算法,而不是调用Windows API。

附录:实验源代码及注释附录一、无任何线程同步机制的代码:os_test2_none.cpp#include <stdio.h>#include <windows.h>#include <ctime>int nAccount1 = 0, nAccount2 = 0; //主线程创建的全局变量DWORD WINAPI Thread1Executive(LPVOID lpParameter);long startTime, endTime;int status = 2;void main(){printf("无线程同步机制:\n\n");HANDLE h1,h2;startTime = clock();h1 = ::CreateThread(NULL,0,Thread1Executive,NULL,0,NULL);h2 = ::CreateThread(NULL,0,Thread1Executive,NULL,0,NULL);::CloseHandle(h1);::CloseHandle(h2);while(1){}}DWORD WINAPI Thread1Executive(LPVOID lpParameter){int nLoop = 0;int nTemp1, nTemp2, nRandom;do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;} while ((nAccount1 + nAccount2) == 0 );printf("循环1次数为%d\n", nLoop);printf("%d,%d\n\n",nAccount1,nAccount2);status --;if(status == 0){endTime = clock();int x = endTime - startTime;printf("所花费时间为:%dms\n",x);}return 0;}附录二、调用系统Mutex互斥变量的代码:os_test2_mutex.cpp#include <stdio.h>#include <windows.h>#include <ctime>int nAccount1 = 0, nAccount2 = 0; //主线程创建的全局变量DWORD WINAPI Thread1Executive(LPVOID lpParameter);HANDLE m1;long startTime, endTime;int status = 2;void main(){printf("解决方案一:调用mutex:\n\n");m1 = CreateMutex(NULL, FALSE, "Sample07");// 检查错误代码if (GetLastError() == ERROR_ALREADY_EXISTS) {CloseHandle(m1);// 如果已有互斥量存在则释放句柄并复位互斥量printf("互斥量m1存在\n");m1 = NULL;return; // 程序退出}HANDLE h1,h2;h1 = ::CreateThread(NULL,0,Thread1Executive,NULL,0,NULL);h2 = ::CreateThread(NULL,0,Thread1Executive,NULL,0,NULL);::CloseHandle(h1);::CloseHandle(h2);while(1){}}DWORD WINAPI Thread1Executive(LPVOID lpParameter){int nLoop = 0;int nTemp1, nTemp2, nRandom;startTime = clock();do{::WaitForSingleObject(m1,INFINITE);nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;if((nAccount1 + nAccount2) != 0)break;::ReleaseMutex(m1);nLoop++;} while (nLoop <= 1000000);printf("循环1次数为%d\n", nLoop);printf("%d,%d\n\n",nAccount1,nAccount2);status --;if(status == 0){endTime = clock();int x = endTime-startTime;printf("所花费时间为:%dms\n",x);}return 0;}附录三、Peterson法实现线程同步的代码:os_test2_peterson.cpp #include <stdio.h>#include <windows.h>#include <ctime>bool flagi = false, flagj = false;enum Turn {i,j};Turn turn = i;int nAccount1 = 0, nAccount2 = 0; //主线程创建的全局变量DWORD WINAPI Thread1Executive(LPVOID lpParameter);HANDLE m1;long startTime, endTime;int status = 2;void main(){printf("解决方案二:peterson法:\n\n");HANDLE h1,h2;startTime = clock();h1 = ::CreateThread(NULL,0,Thread1Executive,NULL,0,NULL);h2 = ::CreateThread(NULL,0,Thread1Executive,NULL,0,NULL);::CloseHandle(h1);::CloseHandle(h2);while(1){}}DWORD WINAPI Thread1Executive(LPVOID lpParameter){int nLoop = 0;int nTemp1, nTemp2, nRandom;do{flagi = true;turn = j;while(flagj && turn == j);nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;if((nAccount1 + nAccount2) != 0)break;flagi = false;nLoop++;} while (nLoop <= 1000000);//printf("循环1次数为%d\n", nLoop);printf("%d,%d\n\n",nAccount1,nAccount2);status --;if(status == 0){endTime = clock();int x = endTime - startTime;printf("所花费时间为:%dms\n",x);}return 0;}。

相关文档
最新文档