操作系统——Windows 线程的互斥与同步

news/2024/10/18 6:10:05/

、实验题目

Windows 线程的互斥与同步

二、实验目的

(1) 回顾操作系统进程、线程的有关概念,加深对 Windows 线程的理解。

(2) 了解互斥体对象,利用互斥与同步操作编写生产者-消费者问题的并发程序,加深对 P (即 semWait)、V(即 semSignal)原语以及利用 P、V 原语进行进程间同步与互斥操作的理解

三、实验内容(实验原理/运用的理论知识、算法/程序流程图、步骤和方法、关键代码)

生产者消费者问题

步骤 1:创建一个“Win32 Consol Application”工程,然后拷贝清单 5-1 中的程序,编译成可执行

文件。

步骤 2:在“命令提示符”窗口运行步骤 1 中生成的可执行文件,列出运行结果。

步骤 3:仔细阅读源程序,找出创建线程的 WINDOWS API 函数,回答下列问题:线程的第一

个执行函数是什么(从哪里开始执行)?它位于创建线程的 API 函数的第几个参数中?

步骤 4:修改清单 5-1 中的程序,调整生产者线程和消费者线程的个数,使得消费者数目大与

生产者,看看结果有何不同。察看运行结果,从中你可以得出什么结论?

步骤 5:修改清单 5-1 中的程序,按程序注释中的说明修改信号量 EmptySemaphore 的初始化方

法,看看结果有何不同。

步骤 6:根据步骤 4 的结果,并查看 MSDN,回答下列问题:

1)CreateMutex 中有几个参数,各代表什么含义。

2)CreateSemaphore 中有几个参数,各代表什么含义,信号量的初值在第几个参数中。

3)程序中 P、V 原语所对应的实际 Windows API 函数是什么,写出这几条语句。

4)CreateMutex 能用 CreateSemaphore 替代吗?尝试修改程序 5-1,将信号量 Mutex 完全用

CreateSemaphore 及相关函数实现。写出要修改的语句。

问题回答:

步骤 3:

创建线程的Windows API函数是CreateThread。

线程的第一个执行函数是Producer函数(生产者线程的入口函数)。它位于CreateThread的第三个参数lpStartAddress中。

步骤 4:

调整生产者线程和消费者线程的个数,使得消费者数目大于生产者,可以观察到以下结果:

当消费者线程数目大于生产者线程数目时,消费者线程可能更频繁地等待缓冲区中有产品可消费,因此消费者线程的执行速度可能较慢。

生产者线程可能更频繁地生产产品,因为消费者线程较慢消耗产品,缓冲区中可能较少空位,导致生产者线程等待EmptySemaphore的次数增加。

步骤 5:

修改信号量EmptySemaphore的初始化方法,将第二个参数设置为0,即初始化为0个空位,代码示例:EmptySemaphore = CreateSemaphore(NULL, 0, SIZE_OF_BUFFER, NULL)。

结果将导致所有的生产者线程在开始时无法生产产品,因为EmptySemaphore信号量初始为0,生产者线程在WaitForSingleObject(EmptySemaphore, INFINITE)处被阻塞,等待消费者线程消耗产品。

步骤 6:

CreateMutex中有3个参数,各代表的含义如下:

参数1:lpMutexAttributes,指向SECURITY_ATTRIBUTES结构的指针,用于设置互斥对象的安全属性。可以为NULL,表示使用默认的安全属性。

参数2:bInitialOwner,指示是否为调用线程拥有互斥对象的初始所有权。TRUE表示拥有,FALSE表示未拥有。

参数3:lpName,互斥对象的名称。可以为NULL。

CreateSemaphore中有4个参数,各代表的含义如下:

参数1:lpSemaphoreAttributes,指向SECURITY_ATTRIBUTES结构的指针,用于设置信号量的安全属性。可以为NULL,表示使用默认的安全属性。

参数2:lInitialCount,信号量的初始计数器值,即可用的资源数量。

参数3:lMaximumCount,信号量的最大计数器值,即计数器的上限。

参数4:lpName,信号量的名称。可以为NULL。信号量的初值在第二个参数lInitialCount中。

P、V原语所对应的实际Windows API函数是:

P操作对应的是WaitForSingleObject函数,用于等待一个对象的信号状态。

V操作对应的是ReleaseSemaphore函数,用于增加信号量的计数器值。

CreateMutex可以用CreateSemaphore替代,但需要做一些修改:

将CreateMutex修改为CreateSemaphore,同时修改互斥锁的初始化和使用方法。

使用WaitForSingleObject来替代WaitForSingleObject(mutex, INFINITE),等待信号量的状态。

使用ReleaseSemaphore来替代ReleaseMutex(mutex),释放信号量。

修改代码示例:

// 初始化互斥锁

mutex = CreateSemaphore(NULL, 1, 1, NULL);

// 生产者线程

WaitForSingleObject(emptySemaphore, INFINITE);

WaitForSingleObject(mutex, INFINITE);

// ...

ReleaseSemaphore(mutex, 1, NULL);

// 消费者线程

WaitForSingleObject(fullSemaphore, INFINITE);

WaitForSingleObject(mutex, INFINITE);

// ...

ReleaseSemaphore(mutex, 1, NULL);

注意,由于CreateSemaphore初始化的互斥锁计数器初始值为1,所以这里使用了1作为CreateSemaphore的初始计数器值,并在WaitForSingleObject和ReleaseSemaphore中将第二个参数设置为1。

四、实验结果与分析

 

实验结果:

程序创建了多个生产者线程和消费者线程。

生产者线程负责生产产品,每次生产后将产品放入缓冲区。

消费者线程负责从缓冲区中取出产品并消耗。

生产者和消费者之间通过互斥锁(Mutex)和信号量(EmptySemaphore和FullSemaphore)实现同步和互斥。

实验分析:

在主函数中,首先创建了互斥锁(Mutex)和两个信号量(EmptySemaphore和FullSemaphore)。互斥锁用于保护共享资源的访问,信号量用于控制生产者和消费者的同步。

根据设置的生产者和消费者数量,创建了相应数量的线程,并分别执行Producer和Consumer函数。

生产者线程在每次生产产品之前,首先等待EmptySemaphore信号量,确保缓冲区有可用的位置。然后获取互斥锁Mutex,进行生产操作,将产品放入缓冲区,并释放互斥锁Mutex和FullSemaphore信号量。

消费者线程在每次消耗产品之前,首先等待FullSemaphore信号量,确保缓冲区中有可用的产品。然后获取互斥锁Mutex,进行消耗操作,从缓冲区中取出产品,并释放互斥锁Mutex和EmptySemaphore信号量。

在每个生产者和消费者的操作中,通过输出语句打印相关信息,包括生产的产品号、缓冲区的状态以及消费的产品号。

主函数中的while循环用于控制程序的运行,当按下回车键时,设置p_ccontinue为false,结束生产者和消费者的线程运行。

由于涉及多线程和同步操作,实际运行结果可能因为线程调度和竞态条件的不确定性而有所不同。以上分析是一种可能的情况。

需要注意的是,这段代码在创建信号量时有两种方式的注释,可以根据需要进行修改,观察对程序运行的影响。

总的来说,这个实验通过模拟生产者和消费者的行为,展示了线程间同步和互斥的机制。生产者和消费者通过缓冲区进行交互,确保生产者不会在缓冲区满时继续生产,消费者不会在缓冲区空时继续消耗。通过互斥锁和信号量的合理运用,保证了线程的安全和正确的执行顺序。

五、小结与心得体会

1.多线程编程:该实验涉及多线程编程,通过创建多个线程并使用线程同步机制实现线程间的协调与通信。

2.生产者-消费者模型:该实验基于生产者-消费者模型,生产者生成产品并放入缓冲区,消费者从缓冲区中取出产品进行消费。

3.缓冲区的使用:缓冲区被设计为循环队列,使用数组来表示。生产者和消费者通过维护缓冲区的读写指针(in和out)来实现对缓冲区的访问。

4.线程同步与互斥:为了避免生产者和消费者同时访问缓冲区而导致数据不一致的问题,使用互斥信号量(Mutex)进行互斥操作。同时,通过同步信号量(FullSemaphore和EmptySemaphore)实现生产者和消费者之间的同步。

5.线程间通信:生产者和消费者之间通过信号量进行通信和同步,当缓冲区满时生产者等待,当缓冲区空时消费者等待。

6.通过以上实验,可以深入理解多线程编程的概念和技术,以及生产者-消费者模型在多线程环境下的应用。这对于并发编程和系统设计有着重要的意义。


http://www.ppmy.cn/news/581087.html

相关文章

【技术选型】Redis的几种集群方案、及优缺点对比

文章目录 背景一、主从模式二、哨兵模式三、Redis Cluster四、各大厂的Redis集群方案客户端分片代理分片Codis 五、Redis集群方案解决方案六、Redis集群方案原理总结 背景 在服务开发中,单机都会存在单点故障的问题,及服务部署在一台服务器上&#xff0…

Windows XP SP3英文版镜像

链接:https://pan.baidu.com/s/1q4Yu6UFXNMIqAaTz_xGyhQ 提取码:09ik

xplorer2 的注册码

425F080378ABC40101110AAF37BA192D8FFDA5C938C82BB729087DD4D824ED7851C9055689ED78A3EF0E577B45BB8880AE5675C4081801376A3BC03B294E67CD0A74816BA96A64B0524E64F015B84EAA5E34F8E5A3457F6237AA30F1E3DF5E69FEE7E50B

Speex for Android

http://blog.csdn.net/chenfeng0104/article/details/7088138 在Android开发中,需要录音并发送到对方设备上。这时问题来了,手机常会是GPRS、3G等方式上网,所以节省流量是非常关键的,使用Speex来压缩音频文件,可以将音…

speex版本下载

speex 作为一个开源的语音编码库,很值得研究。在官网,基本只能下载最新的版本,要了解SPEEX发展脉络,可以在以下地址下载: http://downloads.xiph.org/releases/speex/

Speex之一-介紹Speex

Speex之一-介紹Speex 介紹Speex Speex編解碼器(www.speex.org)存在是因為有這麼一個需求,即是開源同時專利版權也是免費的。這應該也是各開源軟體的必要條件。本質上講,Speex是針對語音的,vorbis是針對語音/音樂的。不像很多基它…

Proxifier v3.21 standard edition 激活码

5EZ8G-C3WL5-B56YG-SCXM9-6QZAP G3ZC7-7YGPY-FZD3A-FMNF9-ENTJB YTZGN-FYT53-J253L-ZQZS4-YLBN9 【Portable Edition】 D5Z6C-U2PGU-5RKWX-D8D7T-HD4UL ZMZ2W-JWTPN-WNP2S-YWTWA-2ZUH6 GYZCP-N3WL7-FETY3-AG7HZ-25THV SDZA7-SY6QA-9GM3K-7U9ZE-29QAD 2BZF4-LWTUS-CJV27-4L…

speex

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 今天测试了speex中带回声消除模块,效果还可以。 测试环境:网络双工通话,16K采样16位编码,speex压缩以及解压.原来通话会听到线路另一端传过来的自己的声音&…