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

该实验通过Windows线程实现生产者-消费者问题,探讨线程同步与互斥。实验涉及创建线程、使用互斥体对象Mutex和信号量Semaphore解决并发问题,调整线程数量观察程序行为变化,以及修改信号量初始化影响。实验强调了线程同步的重要性,展示了Mutex和Semaphore在多线程环境中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

、实验题目

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jakeonil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值