操作系统课程实验实验报告操作系统课程组编实验内容:实验1、实验2姓名:张梦圆仇冠伦学号:20161121272016112130班级:电子2016-04班成绩:西南交通大学电气工程学院报告格式要求1.只需回答每个实验中“实验结果”,需抄写问题。2.正文和标题皆使用小四号宋体字,标题需加粗。参见示例1。3.在回答问题涉及截图时,建议调整截图大小,使其适合阅读并节约版面。4.在回答程序相关的问题时,建议灵活应用文本框和注解图形,以充分说明。参见示例2。5.除了程序正确,正确规范的语言表达也是实验要求重点。因此在实验中注意训练文本表达,准确表述自己的工作重心和亮点。示例1:实验1-1.基础练习实验1-1a.创建命令行应用程序(Win32ConsoleApplication)1.请说明使用的VisualC++版本。答:……2.请对程序执行结果截图。答:……3.请在Windows文件资源管理器中找到该项目目录,请截图说明;并从中找到main.cpp文件、main.obj和学号-1-1a.exe,亦请截图说明。答:……示例2:intmain(){cout“Helloworld.”endl;return0;}在命令行窗口输出字符串”Helloworld”。并退出main函数。实验1-1.线程(Threads)实验1-1a.HelloWorld程序1.请给出程序运行结果的截图。答:2.请结合程序,分析线程t1何时被创建、运行和结束。答:intmain(){//Launchathreadstd::threadt1(call_from_thread);创建线程//Jointhethreadwiththemainthreadt1.join();等待子线程执行完毕之后再继续向下执行主线程return0;线程结束}实验1-1b.多线程并发执行1.请给出程序运行结果的截图。答:2.请分析程序输出结果是否固定。答:主函数也是一条线程,通常叫做主线程,所以上面的代码实际上有11条线程在运行。程序创建线程组,其线程的运行存在先后秩序不确定的现象。实验1-1c.线程中函数的参数1.请给出程序运行结果的截图。答:2.请分析程序输出内容的格式不整齐的原因。答:有i+1个线程在竞争运行,程序内的11条线程都在竞争性地使用stdout这个公共资源,所以输出结果不整齐。实验1-2.线竞争状态(Raceconditions)1.请给出程序运行结果的截图。答:2.请结合程序,解释程序中线程为何出现竞争状态。答:由于本例中使用多个线程模拟多个用户对广告的点击,存在多个线程同时访问同一个类(对象或方法),而在这种情况下,多个线程都能同时获取以及改变共享数据,竞争危害便发生了。因为各个线程对数据操纵的顺序并不可预知,因此数据改变的结果取决于线程最终的运行顺序。所有的线程都在“Racing”(竞争)以优先获取数据改变数据。实验1-3.互斥锁实验1-3a.互斥锁(Mutex)1.请给出程序运行结果的5个截图。答:2.请结合程序,分析如何通过互斥锁解决竞争状态。答:由于多线程之间共享全局变量就会导致出现资源竞争的问题,为了避免这种竞争出现,利用互斥锁可以实现线程同步,解决竞争状态。longtotal=0;std::mutexm;//对共享资源进行保护的互斥对象voidclick(){m.lock();//访问之前,锁定互斥对象,对线程上锁,此时其他线程阻塞等待该线程释放锁for(inti=0;i100000;++i){total+=1;}m.unlock();//访问完成后,释放互斥对象,等待下一个线程运行}3.将mutex的锁定和释放放到for循环之内,测试结果,并分析其效果与当前程序有何不同。答:与之前相比,时间明显增加。实验1-3b.lock_guard模板类1.请给出程序运行结果的2个截图。答:2.请结合程序,分析lock_guard如何使用互斥锁解决竞争状态。答:Lock_guard是Mute的优秀辅助,此类辅助锁定互斥量,构造时锁定,析构时解锁,避免遗忘解锁,也就是说在其作用域内它会一直锁定要求的变量,以此实现线程同步,解决竞争状态。3.分析实验1-3a和实验1-3b的程序在执行时间上的性能差异。答:本题的两个例子我没看出执行时间上的性能差异。使用mutex互斥锁,来保证线程的安全性.但是这样是很麻烦的.我们需要手动的对锁进行操作.如果出现多个分支的情况,则需要多次书写unlock操作。引入lock_guard对象,可实现在作用域内的上锁与自动解锁。实验1-3c.原子(Atomic)1.请给出程序运行结果的截图。答:2.请结合程序,分析如何通过原子容器解决竞争状态。答:引入原子操作的概念,并通过#includeatomic这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool,atomic_int等等,如果我们在多个线程中对这些类型的共享资源进行操作,编译器将保证这些操作都是原子性的,也就是说,确保任意时刻只有一个线程对这个资源进行访问,编译器将保证,多个线程访问这个共享资源的正确性。从而避免了锁的使用,解决了竞争状态,提高了效率。实验2-1.条件变量(Conditionvariables)1.请给出程序运行结果的截图。答:2.请结合程序,说明本程序实现的功能,以及条件变量在print_id和go函数中起的作用。答:条件变量的作用是用于多线程之间关于共享数据状态变化的通信。当一个动作需要另外一个动作完成时才能进行,即:当一个线程的行为依赖于另外一个线程对共享数据状态的改变时,这时候就可以使用条件变量在print_id函数中:如果标志位不为true,则等待,当前线程被阻塞,当全局标志位变为true之后,线程被唤醒,继续往下执行打印线程编号id。在go函数中:先设置全局标志位为true,唤醒所有线程。实验2-2.信号量(Semaphore)1.请给出程序运行结果的截图。答:2.请结合程序,解释如何用条件变量和互斥锁实现信号量。答:条件变量常与互斥锁同时使用,条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生,达到线程同步的目的:条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足。在发送信号时,如果没有线程等待在该条件变量上,那么信号将丢失;而信号量有计数值,每次信号量post操作都会被记录。实验2-3.生产者-消费者问题1.请给出程序运行结果的截图。答:2.请结合程序,分析以上程序有何问题,如何修改,并给出修改后的程序。答:程序缺少头文件semaphore.h,在程序中加入头文件semaphore.h即可#pragmaonce#includemutex#includecondition_variableclasssemaphore{private:std::mutexmtx;std::condition_variablecv;intcount;public:semaphore(intcount_=0):count(count_){;}voidnotify(){std::unique_lockstd::mutexlck(mtx);++count;cv.notify_one();}voidwait(){std::unique_lockstd::mutexlck(mtx);while(count==0){cv.wait(lck);}count--;}};实验2-4.死锁(Deadlock)1.请分别给出步骤1和步骤2程序运行结果的截图。答:步骤一:步骤2:2.请结合程序,分析以上程序为何有时出现死锁,何时出现死锁。答:在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。互斥:资源不能共享,只能由一个进程持有,资源只能由phi0或phi1单独占用。占有且等待:当一个等待另外进程而阻塞时,资源不主动释放。当程序执行s0.wait()或s1.wait()时不主动释放该资源。不可抢占:操作系统不能强行抢占被进程持有的资源循环等待:存在一个封闭的进程链,使得每一个进程都至少占有下个进程所需要的资源