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

合集下载

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

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

进程(线程)同步和互斥实验报告操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期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.实验操作步骤(1)设计和实现多线程程序,包括生产者线程、消费者线程、读者线程和写者线程。

(2)使用互斥锁和条件变量对共享资源进行同步操作,保证线程的安全性。

(3)编译并运行程序,观察线程的执行顺序和结果是否符合预期。

四、实验结果与分析1.生产者/消费者问题通过设计合适的缓冲区和互斥锁,保证生产者线程和消费者线程的安全访问。

实验结果表明,生产者线程可以正确地生产产品,并将产品存储到缓冲区中。

消费者线程可以从缓冲区中取出产品并消费。

2.读者/写者问题通过使用互斥锁和条件变量,实现多个读者线程可以同时读取共享资源,但是写者线程获取写权限后,其他线程无法读取或写入。

实验结果表明,读者线程可以同时读取共享资源,而写者线程获取写权限后,其他线程无法读取或写入。

五、实验总结本实验通过对操作系统线程同步机制的实验,深入了解了操作系统中线程的运行和同步原理,掌握了线程同步机制的使用方法以及安全性问题。

实验结果表明,在设计合适的缓冲区和使用适当的同步机制的情况下,可以有效地保证线程的安全性和正确的并发执行。

六、实验心得通过本次实验,我深刻理解了线程同步机制在操作系统中的重要性。

线程同步机制可以保证多个线程正确地访问共享资源,避免竞态条件等问题的出现。

操作系统 实验四 线程同步

操作系统 实验四 线程同步

集美大学计算机工程学院实验报告课程名称:操作系统指导教师:王丰实验成绩:实验编号:实验四实验名称:线程同步班级:计算12姓名:学号:上机实践日期:2015.5上机实践时间:2学时一、实验目的1、掌握在Linux环境下的线程创建: clone();2、线程同步:信号灯sem_t实现线程同步与互斥;3、实现经典同步问题读者-写者问题。

二、实验环境Ubuntu-VMware、Linux三、实验内容1、用信号灯 + PV操作实现读者—写者问题;2、用clone()函数4个读者线程和4个写者线程;3、每次读者在共享数据区(缓冲区)读操作,或者写者在共享数据区写操作时,要显示当前正在操作的线程;4、按读者优先或者写者优先编写程序,但要明确是那个优先。

函数和变量1)信号灯:头部文件:semaphore.h (线程:pthread.h)2)信号灯初始化:sem_t r_w_w, mutex;//定义信号灯初始化:sem_init(&r_w_w, 0, 1);sem_init(&mutex,0, 1);3)信号灯操作:对信号等进行P操作:sem_wait(&r_w_w);sem_wait(&mutex);对信号灯进行V操作:sem_post(&r_w_w);Sem_post(&mutex);四、实现过程#include <stdio.h>#include <semaphore.h>#include <pthread.h>#include <stdlib.h>#include <sched.h>//定义信号灯变量sem_t r_w_w;sem_t mutex;int readCount=0;char info[20];//共享数据区int Reader(int r_n){char rc[20];while(1){sem_wait(&mutex);readCount++;if(readCount==1){sem_wait(&r_w_w);printf(“First reader inter CR!\n”); }sem_post(&mutex);printf(“ %dth reader is reading:”,r_n);strcpy(rc,info);printf(“%s\n”,rc);sem_wait(&mutex);readCount--;if(readCount==0)sem_post(&r_w_w);printf(“%dth reader exit.\n”,r_n);sem_post(&mutex);}}int Writer(int w_n){char ws[20];sprintf(ws,”%dth writer”,wn);while(1){sem_wait(&r_w_w);strcpy(info,ws);sem_post(&r_w_w);}}main(){int i,arg;int clone_flag;char *stack;sem_init(&r_w_w,0,1);sem_init(&mutex,0,1);clone_flag=CLONE_VM|CLONE_SIGHAND |CLONE_FS|CLONE_FILES; for(i=0;i<4;i++){arg=i+1;stack=(char *) malloc(4096);clone((void *)Reader,&(stack[4096]),clone_flag,(void *)&arg);stack=(char *) malloc(4096);clone((void *)Writer,&(stack[4096]),clone_flag,(void *)&arg);}exit(1);}1)查看当前root目录下文件2)将ls输出,输入到文件ttt中3)查看4)向文件ttt中追加内容3.后台进程、管道操作①后台命令后台执行进程a.out4.Shell程序①无参数的Shell程序②shell程序的位置参数1)编写shell程序2)编译及运行结果分析:在运行时带了5个参数,于是argc=5,然后将这五个参数依次输出到屏幕。

操作系统实验线程的同步

操作系统实验线程的同步

实验六线程的同步1、实验目的(1)进一步掌握Windows系统环境下线程的创建与撤销。

(2)熟悉Windows系统提供的线程同步API。

(3)使用Windows系统提供的线程同步API解决实际问题。

2、实验准备知识:相关API函数介绍①等待对象等待对象(wait functions)函数包括等待一个对象(WaitForSingleObject())和等待多个对象(WaitForMultipleObject())两个API函数。

1)等待一个对象WaitForSingleObject()用于等待一个对象。

它等待的对象可以为以下对象之一。

·Change ontification:变化通知。

·Console input: 控制台输入。

·Event:事件。

·Job:作业。

·Mutex:互斥信号量。

·Process:进程。

·Semaphore:计数信号量。

·Thread:线程。

·Waitable timer:定时器。

原型:DWORD WaitForSingleObject(HANDLE hHandle, // 对象句柄DWORD dwMilliseconds // 等待时间);参数说明:(1)hHandle:等待对象的对象句柄。

该对象句柄必须为SYNCHRONIZE访问。

(2)dwMilliseconds:等待时间,单位为ms。

若该值为0,函数在测试对象的状态后立即返回,若为INFINITE,函数一直等待下去,直到接收到一个信号将其唤醒,如表2-1所示。

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

Static HANDLE hHandlel = NULL;DWORD dRes;dRes = WaitForSingleObject(hHandlel,10); //等待对象的句柄为hHandlel,等待时间为10ms 2)等待对个对象WaitForMultiple()bject()在指定时间内等待多个对象,它等待的对象与WaitForSingleObject()相同。

建立线程的实验报告(3篇)

建立线程的实验报告(3篇)

第1篇一、实验目的1. 理解线程的概念和作用;2. 掌握在C++中创建和使用线程的方法;3. 了解线程同步机制,如互斥锁、条件变量等;4. 分析线程间的通信和协作。

二、实验环境1. 操作系统:Windows 102. 编译器:Visual Studio 20193. 编程语言:C++三、实验内容本次实验主要分为以下几个部分:1. 线程的基本概念和作用;2. 创建和使用线程;3. 线程同步机制;4. 线程间的通信和协作。

四、实验步骤1. 线程的基本概念和作用线程是程序执行过程中的一个独立单位,它包含程序执行所需的基本信息,如程序计数器、寄存器等。

线程的主要作用是提高程序的执行效率,实现并发执行。

2. 创建和使用线程在C++中,可以使用`std::thread`类来创建线程。

以下是一个简单的例子:```cppinclude <iostream>void printNumber(int n) {for (int i = 0; i < n; ++i) {std::cout << i << std::endl;}}int main() {std::thread t1(printNumber, 10); // 创建线程,传入函数和参数std::thread t2(printNumber, 20);t1.join(); // 等待线程t1执行完毕t2.join(); // 等待线程t2执行完毕return 0;}```在上面的代码中,我们创建了两个线程`t1`和`t2`,分别执行`printNumber`函数。

使用`join`函数可以等待线程执行完毕。

3. 线程同步机制线程同步机制用于解决多线程在执行过程中可能出现的数据竞争、死锁等问题。

以下是一些常用的线程同步机制:(1)互斥锁(Mutex)互斥锁用于保护共享资源,确保同一时刻只有一个线程可以访问该资源。

以下是一个使用互斥锁的例子:```cppinclude <iostream>include <mutex>std::mutex mtx;void printNumber(int n) {mtx.lock(); // 获取互斥锁for (int i = 0; i < n; ++i) {std::cout << i << std::endl;}mtx.unlock(); // 释放互斥锁}int main() {std::thread t1(printNumber, 10);std::thread t2(printNumber, 20);t1.join();t2.join();return 0;}```(2)条件变量(Condition Variable)条件变量用于在线程间实现等待和通知机制。

线程同步实验报告(A39)

线程同步实验报告(A39)

广州商学院操作系统实验报告(第4次)实验名称:实验六线程同步一、实验目的1. 加深理解线程同步的概念及实现线程同步的原理。

2. 掌握Linux线程库支持的信号量同步机制和信号量互斥机制,学会通过信号量信号实现线程间的同步与互斥。

二、实验内容实验七、线程同步实现公交车司机与售票员同步,参考实验四,完成该程序的设计三、原理和实验主要步骤1、原理:Linux的线程库中定义了同步信号量以及多种同步信号量操作函数(原语)。

POSIX信号量同步信号量的类型为sem_t基本的同步信号量操作函数有4个:sem_init( )sem_wait( )(相当于P操作)sem_post( )(相当于V操作)sem_destroy( )它们均在头文件semaphore.h中声明。

sem_init 函数原型:int sem_init(sem_t *sem, int type, int value);其中,参数sem为同步信号量的指针;type为信号量类型,若为0,表示该信号量是现行进程的局部信号量(只在现行进程的线程之间使用),否则,它可为多个进程所共享;value 是信号量值的初值。

功能:初始化同步信号量。

sem_wait 函数原型:int sem_wait(sem_t *sem);功能:同步信号量的P操作sem_post 函数原型:int sem_post(sem_t *sem);功能:同步信号量的V操作sem_destroy 函数原型:int sem_destroy(sem_t *sem);功能:清理同步信号量上述函数返回0表示成功,非0表示失败。

2、本实验要求应用Linux线程库支持的信号量互斥机制改进实验4.2,即程序test4_2.c。

该互斥机制的内容见讲义Unit 4中的4.2节。

本实验的程序框架和部分程序代码如下,请完成该程序的设计,/*test6_1.c*/#include<stdio.h>#include<pthread.h>int ticket[10]={1,3,5,7,9,2,4,6,8,10};int rest=10;int th_num[2]={1,2}; /*自定义的线程序号*/<定义一个互斥信号量>void *terminal(void *p) /*售票终端线程代码*/{ int mynum=*((int *)p); /*本终端的序号*/int tot=0; /*本终端售票计数*/<你的设计部分>printf(“Terminal_%d selled %d tickets .\n”, mynum,tot);pthread_exit(0);}int main( ){pthread_t tid[2];<初始化信号量>pthread_create(&tid[0], NULL, terminal, &th_num[0]);/*参数“&th_num[0]”是线程的入口参数*/pthread_create(&tid[1], NULL, terminal, &th_num[1]);<等待线程终止><撤消信号量><结束>}问题描述:公共汽车上,司机和售票员的活动分别是:司机的活动:启动车辆;正常行车;到站停车。

同步机制实验报告

同步机制实验报告

一、实验目的1. 理解同步机制的基本概念和原理;2. 掌握不同同步机制(如互斥锁、条件变量、信号量等)的使用方法;3. 通过实验验证同步机制在解决并发编程中的同步和互斥问题。

二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 2019三、实验内容本次实验主要涉及以下同步机制:1. 互斥锁(Mutex)2. 条件变量(Condition Variable)3. 信号量(Semaphore)1. 互斥锁(Mutex)(1)实验目的:验证互斥锁在解决临界区访问冲突问题中的作用。

(2)实验步骤:1)定义互斥锁对象;2)创建多个线程,每个线程尝试访问临界区;3)在访问临界区之前,使用互斥锁进行加锁和解锁操作。

(3)实验结果:实验结果显示,在多个线程访问临界区时,互斥锁成功避免了冲突,确保了临界区的安全访问。

2. 条件变量(Condition Variable)(1)实验目的:验证条件变量在解决生产者-消费者问题中的作用。

(2)实验步骤:1)定义条件变量对象和互斥锁对象;2)创建生产者线程和消费者线程;3)生产者在生产数据时,使用条件变量通知消费者;4)消费者在消费数据时,使用条件变量等待生产者通知。

(3)实验结果:实验结果显示,在多个生产者和消费者线程并发执行时,条件变量成功实现了生产者和消费者之间的同步,避免了生产者和消费者之间的冲突。

3. 信号量(Semaphore)(1)实验目的:验证信号量在解决线程同步问题中的作用。

(2)实验步骤:1)定义信号量对象;2)创建多个线程,每个线程在执行任务前,需要等待信号量释放;3)在任务完成后,释放信号量,以便其他线程执行。

(3)实验结果:实验结果显示,在多个线程并发执行时,信号量成功实现了线程之间的同步,确保了线程按照预期顺序执行。

四、实验总结通过本次实验,我们深入了解了同步机制的基本概念和原理,掌握了互斥锁、条件变量和信号量等同步机制的使用方法。

Windows的多线程同步实验报告

Windows的多线程同步实验报告

一、实验目的在掌握基于消息的windows程序结构和多线程程序设计方法的基础上,设计一个多线程同步的程序。

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

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

进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。

线程是进程内部的一个执行单元。

系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows系统。

主执行线程终止了,进程也就随之终止。

每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。

用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。

一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。

多线程可以实现并行处理,避免了某项任务长时间占用CPU时间。

要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。

由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能。

这一点在多线程编程时应该注意。

Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作。

线程同步机制实验报告

线程同步机制实验报告

线程同步机制实验报告通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性。

然后利用现有操作系统提供的同步机制编程实现关于该两个线程的有序控制,同时要求根据同步机制的Peterson软件解决方案尝试自己编程实现同步机制和用于同一问题的解决,并基于程序运行时间长短比较两种同步机制。

二、实验内容:1、基于给定银行账户间转账操作模拟代码作为线程执行代码,在主线程中创建两个并发线程,编程实现并观察程序运行结果和予以解释说明。

(无同步机制)2、利用Win32 API中互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量操作函数调用的正确位置。

3、根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制和用于上述线程并发问题的解决,并基于程序运行时间长短将其与基于Win32 API互斥信号量的线程同步机制的效率展开比较。

其间,可规定线程主体代码循环执行1000000次。

三、实验环境:操作系统:Windows 7软件:VC++6.0●本实验包含三个基于并发线程的程序,第一个没有同步机制,第二个利用Win32 API中互斥信号量操作函数解决线程并发问题,第三个根据同步机制的Peterson软件解决方案实现线程同步机制并解决线程并发问题。

三个程序拥有相同的线程主体:线程主体设计:do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;} while ((nAccount1 + nAccount2)==0);该线程主体是对银行账户间转账操作模拟的模拟,可知,若并发的线程不发生交叉,则依次转账操作后nAccount1 + nAccount2的值永远为0,程序不会跳出循环,如果线程发生交叉,则经过若干次转账操作后,就有可能出现nAccount1 + nAccount2不为0的情况,此时程序跳出循环。

线程控制实验报告(3篇)

线程控制实验报告(3篇)

第1篇一、实验背景线程是操作系统中实现并发执行的基本单位,它允许程序在同一时间内执行多个任务。

线程控制实验旨在通过实际操作,加深对线程概念、线程同步与互斥机制的理解,并掌握线程的创建、同步与互斥方法。

二、实验目的1. 理解线程的概念及其在操作系统中的作用。

2. 掌握线程的创建、同步与互斥方法。

3. 熟悉线程调度与同步在实际编程中的应用。

4. 通过实验,提高对多线程编程的理解和实际操作能力。

三、实验环境操作系统:Windows 10编程语言:Java开发工具:Eclipse四、实验内容1. 线程的创建与启动实验步骤:(1)创建一个名为ThreadDemo的Java类,继承自Thread类。

(2)在ThreadDemo类中重写run()方法,实现线程要执行的任务。

(3)在main方法中创建ThreadDemo类的实例,并调用start()方法启动线程。

实验代码:```javapublic class ThreadDemo extends Thread {@Overridepublic void run() {// 线程要执行的任务System.out.println("线程运行:" +Thread.currentThread().getName());}public static void main(String[] args) {ThreadDemo threadDemo = new ThreadDemo();threadDemo.start(); // 启动线程}}```2. 线程同步与互斥实验步骤:(1)创建一个名为SyncDemo的Java类,包含一个共享资源和一个同步方法。

(2)在SyncDemo类中,使用synchronized关键字声明同步方法,实现线程间的同步。

(3)在main方法中创建多个ThreadDemo类的实例,并启动线程,观察线程同步与互斥的效果。

实验代码:```javapublic class SyncDemo {private int count = 0;public synchronized void increment() {count++;System.out.println(Thread.currentThread().getName() + ":count=" + count);}public static void main(String[] args) {SyncDemo syncDemo = new SyncDemo();Thread thread1 = new Thread(() -> {for (int i = 0; i < 5; i++) {syncDemo.increment();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5; i++) {syncDemo.increment();}});thread1.start();thread2.start();}}```3. 线程通信实验步骤:(1)创建一个名为ThreadCommunication的Java类,包含一个共享资源和一个同步方法。

实用操作系统实验:Windows环境下线程的同步

实用操作系统实验:Windows环境下线程的同步

课程上机报告
课程名称________________实用操作系统实验_________
题目_____Windows XP环境下线程的同步___ _
指导教师____________________________________
设计起止日期___________________________________
学院___信息管理学院___
专业__________________
学生姓名__________________
班级/学号__________________
成绩_____________
北京信息科技大学
信息管理学院
(课程上机)实验报告
1.实验名称、实验目的、实验内容、实验要求由教师确定,实验前由教师事先填好,然后作为实验报告模版供学生使用;
2.实验准备由学生在实验或上机之前填写,教师应该在实验前检查;
3.实验过程由学生记录实验的过程,包括操作过程、遇到哪些问题以及如何解决等;
4.实验总结由学生在实验后填写,总结本次实验的收获、未解决的问题以及体会和建议等;
5.源程序、代码、具体语句等,若表格空间不足时可作为附录另外附页。

重庆大学操作系统实验三(线程同步)

重庆大学操作系统实验三(线程同步)

重庆大学操作系统实验三(线程同步)重庆大学学生实验报告实验课程名称操作系统原理开课实验室重庆大学DS1501 学院软件工程年级 2013 专业班学生姓名学号开课时间 2015 至 2016 学年第一学期重庆大学软件学院制《操作系统原理》实验报告三、使用仪器、材料(软硬件开发环境)Notepad++expenv四、实验步骤(实现的过程)//定义信号量结构体struct semaphore{int value;/*processes blocked by this semaphore*/struct wait_queue*wq_kbd;};sem.c:void*sys_sem_create(int value){struct semaphore*hsem;char*p;p=(char*)kmalloc(sizeof(struct semaphore));hsem=(struct semaphore*)p;hsem->value=value;//赋初值hsem->wq_kbd=NULL;//非常重要if(hsem==NULL)return NULL;else return(struct semaphore*)hsem;//成功返回信号量句柄hsem }int sys_sem_destroy(void*hsem){kfree(hsem);return0;}int sys_sem_wait(void*hsem){uint32_t flags;save_flags_cli(flags);((struct semaphore*)hsem)->value--;//P操作if(((struct semaphore*)hsem)->value<0){sleep_on(&(((struct semaphore*)hsem)->wq_kbd));}restore_flags(flags);return0;}int sys_sem_signal(void*hsem){uint32_t flags;save_flags_cli(flags);((struct semaphore*)hsem)->value++;//V操作if(((struct semaphore*)hsem)->value<=0){wake_up(&(((struct semaphore*)hsem)->wq_kbd),1);//等待队列中唤醒一个线程}restore_flags(flags);return0;}把这四个函数做成系统调用 sem_create/destroy/wait/signalgraphics.c中//定义一个表示信号量的全局变量static void*hsem=NULL;hsem=sem_create(1);//创建信号量sem_destroy(hsem);//销毁信号量以及sem_wait(hsem);//用信号量hsem保护画点临界区switchBank(HIWORD(addr));*p=getBValue(cr);*(p+1)=getGValue(cr);*(p+2)=getRValue(cr);sem_signal(hsem);main.c:声明信号量:# define arrayNumber50#define N4//缓冲区数static void*mutex=NULL;//互斥信号量static void*full=NULL;//已生产产品数static void*empty=NULL;//空闲数int startposition=0;//生产者缓冲区坐标static int count=0; //消费者缓冲区坐标int temp[4][50]={0};int array[N][arrayNumber];生产者消费者函数:void tsk_producer(void*pv){while(1){int i=0;srand((unsigned)time(NULL));sem_wait(empty);//是否有空闲位置?sem_wait(mutex);for(i=0;i<=arrayNumber-1;i++){array[startposition][i]=random()%200;draw(i*10,startposition*230,startposition*230+array[startpo sition][i]);DELAY(100000);}startposition=(++startposition)%N;sem_signal(mutex);sem_signal(full);//有产品生产好}task_exit(0);}void tsk_consumer(void*pv){while(1){sem_wait(full);//还有产品么?sem_wait(mutex);int i;for(i=0;i<=arrayNumber-1;i++){temp[count][i]=array[count][i];}sem_signal(mutex);//让出临界区使生产与消费并行sort_m(temp[count],arrayNumber,count*230); //冒泡排序resetAllBK(temp[count],arrayNumber,count*230); //清空该缓冲区count=(++count)%N;sem_signal(empty);//消费完一个产品}task_exit(0);}主函数:int value=1;mutex=sem_create(value);value=0;full=sem_create(value);value=N;empty=sem_create(value);initGraphics(0x0118);unsigned char*stack_producer=(unsigned char*)malloc(1024*1024);unsigned char*stack_consumer=(unsigned char*)malloc(1024*1024);inttid_producer=task_create(stack_producer+1024*1024,tsk_produ cer,(void*)0);inttid_consumer=task_create(stack_consumer+1024*1024,tsk_cons umer,(void*)0);int setResult1=setpriority(tid_producer,2);int setResult2=setpriority(tid_consumer,2);五、实验结果及分析(实现的效果,包括屏幕截图、系统总体运行情况和测试情况等)empty=sem_create(value);initGraphics(0x0118);unsigned char*stack_producer=(unsigned char*)malloc(1024*1024);unsigned char*stack_consumer=(unsigned char*)malloc(1024*1024);inttid_producer=task_create(stack_producer+1024*1024,tsk_produ cer,(void*)0);inttid_consumer=task_create(stack_consumer+1024*1024,tsk_cons umer,(void*)0);int setResult1=setpriority(tid_producer,2);int setResult2=setpriority(tid_consumer,2);五、实验结果及分析(实现的效果,包括屏幕截图、系统总体运行情况和测试情况等)通过互斥量保护Setpixel解决了实验二优先级调度的花屏现象通过做本实验,我对书本上信号量概念有了实践性的理解。

  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;}。

相关文档
最新文档