ImageVerifierCode 换一换
格式:DOCX , 页数:29 ,大小:167.75KB ,
资源ID:12482953      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12482953.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(实验3同步机制.docx)为本站会员(b****0)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

实验3同步机制.docx

1、实验3同步机制实验 3 同步机制实验内容 :学习 Windows 有关进程 /线程同步的背景知识和 API ,学习 windows 平台下常用的同步 方式,并分析 2 个实验程序 (利用信号量实现两个进程间的同步和利用互斥量实现读者写者 问题),观察程序的运行情况并分析执行结果。实验目的 :在本实验中,通过对互斥量( Mutex)和信号量(Semaphore)对象的了解,来加深对Windows 进程、线程同步的理解。(1)了解互斥量和信号量对象。(2)通过分析实验程序,理解管理信号量对象的 API 。(3)理解在进程中如何使用信号量对象。(4)通过分析实验程序,理解在线程中如何使用互斥量对象。

2、(5)理解父进程创建子进程的程序设计方法,理解在主线程中创建子线程的方法。 实验要求:(1)理解 Windows 有关进程 /线程同步的背景知识和 API 。(2)按要求运行 2 个程序,观察程序执行的结果,并给出要求的结果分析。 实验选做部分:(3)参照 3-2 程序,写出一个实现单个生产者消费者问题的算法,可以使用单个缓冲区, 也可以使用缓冲池, 生产者随机产生任意形式的数据并放入缓冲区中, 消费者则以随机 的时间间隔从缓冲区中取数据,随机时间请使用随机数产生。并发与同步的背景知识更多的、更详细的参考资料和代码举例在文件夹“进程线程程序设计及同步机制的学 习资料”中,请利用课余时间仔细阅读

3、。Windows 开发人员可以使用同步对象来协调线程和进程的工作, 以使其共享信息并执行 任务。此类对象包括互斥量 Mutex、信- 号量 Semaphore 事件 Eve nt等。多进程、多线程编程中关键的一步是保护所有的共享资源 ,工具主要有互斥量 Mutex和信号量Semaphore等;另一个是协调线程使其完成应用程序的任务 ,为此,可利用内核中的信号量对象或事件对象。互斥量是一个可命名且安全的内核对象, 主要目的是引导对共享资源的访问。 拥有单一 访问资源的线程创建互斥体, 所有希望访问该资源的线程应该在实际执行操作之前获得互 斥体, 而在访问结束时立即释放互斥体 ,以允许下一个等待线

4、程获得互斥体, 然后接着进行 下去。利用 CreateMutex() API 可创建互斥量,创建时可以指定一个初始的拥有权标志,通过 使用这个标志, 只有当线程完成了资源的所有的初始化工作时, 才允许创建线程释放互斥体。为了获得互斥体,首先,想要访问调用的线程可使用 OpenMutex() API 来获得指向对象的句柄; 然后, 线程将这个句柄提供给一个等待函数。 当内核将互斥体对象发送给等待线程 时, 就表明该线程获得了互斥体的拥有权。 当线程获得拥有权时, 线程控制了对共享资源的 访问必须设法尽快地放弃互斥体。放弃共享资源时需要在该对象上调用 ReleaseMutex()API 。然后系统

5、负责将互斥量拥有权传递给下一个等待着的线程 (由到达时间决定顺序 ) 。信号量 Semaphore 与互斥量 Mutex 的用法不同,互斥量 Mutex 保证任意时刻只能有一 个进程或线程获得互斥体,信号量允许多个线程同时使用共享资源,这与操作系统中的 Wait/Signal 操作【 也称 PV 操作 】相同。它指出了同时访问共享资源的线程最大数目。 它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程 数目。在用CreateSemaphore ()创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数或者 0。每增

6、加一个线程对共享资源的访问,当前可用资源计数就会减 1,只要当前可用资源计数是大于 0 的,就可以发出信号量信号。 但是当前可用计数减小到 0 时则说明当前占用资源的线程数已经达到了所允 许的最大数目, 不能在允许其他线程的进入, 此时的信号量信号将无法发出。 线程在处理完 共享资源后,应在离开的同时通过 ReleaseSemaphore()函数将当前可用资源计数加 1。在任何时候当前可用资源计数决不可能大于最大资源计数。此外, windows 还提供了另外一个容易误导大家理解的同步对象,取名为 CriticalSection,中文取名为临界区,请大家注意与课本讲的临界资源、临界区的概念相区分

7、。课本 上临界区指“对临界资源进行访问的代码” ;而这种称为“ Critical Section ”互斥机制,并不 是这个意思,而是访问临界区之前的一种加锁机制,与互斥量 Mutex 的作用类似,只是“ Critical Section ”互斥机制只能在同一进程内部各个线程间使用,而 Mutex互斥机制是可以跨进程使用的。实验内容与步骤1.信号量Semaphore对象清单 3-1 程序展示如何在进程间使用信号量对象。父进程启动时,利用 CreateSemaphore () API 创建一个命名的、可共享的信号量对象, 并利用CreateProcess(创建子进程,然后调用 WaitForSin

8、gleObject ()函数去获取信号量,但是由于信号量的初始值为 0,所以父进程阻塞在此, 无法成功占有信号量; 子进程创建后, 调用OpenSemaphore ()打开父进程创建的信号量,然后调用 ReleaseSemaphore ()函数释放了 1 个信号量, 此后, 处于阻塞状态的父进程获取了子进程释放的信号量, 从而解除了阻 塞,继续运行至程序结束。清单 3-1 创建和打开信号量对象在进程间传送信号/ Semaphore 信号量项目#include #include #include / 定义一个信号量的名字static LPCTSTR g_szSemaphoreName = shm

9、tu.os2012.semaphore;/ 本方法只是创建了一个进程的副本,以子进程模式 (由命令行指定 ) 工作BOOL CreateChild ()/ 提取当前可执行文件的文件名 TCHAR szFilenameMAX_PA TH ;GetModuleFileName(NULL, szFilename, MAX_PA TH) ;/ 格式化用于子进程的命令行,指明它是一个 EXE 文件和子进程 TCHAR szCmdLineMAX_PA TH ;sprintf(szCmdLine, %s child , szFilename) ;/ 子进程的启动信息结构 STARTUPINFO si;Zer

10、oMemory(reinterpret_cast(&si), sizeof(si) ; si.cb = sizeof(si); / 必须是本结构的大小/ 返回的子进程的进程信息结构 PROCESS_INFORMA TION pi;/ 使用同一可执行文件和告诉它是一个子进程的命令行创建进程BOOL bCreateOK = szFilename, szCmdLine,NULL,NULL, FALSE,CreateProcess(/ 生成的可执行文件名/ 指示其行为与子进程一样的标志/ 子进程句柄的安全性/ 子线程句柄的安全性/ 不继承句柄CREATE_NEW_CONSOLE, / 特殊的创建标志N

11、ULL,NULL, &si, &pi ) ;/ 新环境/ 当前目录/ 启动信息结构/ 返回的进程信息结构/ 释放对子进程的引用if (bCreateOK)CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return(bCreateOK) ;/ 下面的方法创建一个信号量和一个子进程,然后等待子进程在返回前释放一个信号 void WaitForChild ()HANDLE hSemaphore = CreateSemaphore( / 创建一个信号量 ,初始值 0 ,最大值为 1 NULL, / 缺省的安全性,子进程将具有访问权限0, /初始值

12、 01, /最大值为 1 g_szSemaphoreName / 信号量名称 );if (hSemaphore != NULL)cout 信号量对象已经建立啦。 endl;/ 创建子进程if ( CreateChild()cout 父进程建立了一个子进程 endl;/ 等待,直到子进程发出信号cout 因为当前信号量的值为 0,所以父进程暂时阻塞在此啦 . endl;WaitForSingleObject(hSemaphore, INFINITE);cout 因为子进程释放了 1 个信号量,所以,父进程可以解除阻塞啦。 endl; / 清除句柄CloseHandle(hSemaphore);

13、hSemaphore=INVALID_HANDLE_V ALUE;/ 以下方法在子进程模式下被调用,其功能只是释放 1 个信号量void SignalParent()/ 尝试打开句柄cout child process begining endl;HANDLE hSemaphore = OpenSemaphore( SEMAPHORE_ALL_ACCESS, / 所要求的最小访问权限 FALSE, / 不是可继承的句柄g_szSemaphoreName); / 信号量名称if(hSemaphore != NULL)cout 如果你同意释放一个信号量,请按任意键 endl; getchar();

14、cout 此刻,子进程释放了 1 个信号量 . 1 & strcmp(argv1 , child )= 0)/ 向父进程发出信号 SignalParent() ; cout 子进程马上就要运行结束了。请按任意键继续。 endl ;else/ 创建一个信号量并等待子进程 WaitForChild();cout 父进程马上就要运行结束了。请按任意键继续。 4zJ adl- Linef A * -NLd fWl 阳IB /tiX 3/Dd/U WNUIT /3-DEBIJIT 柏,fc MBCSTjFjjTihutreenfciph+eximtie.fjnw 斤解DEuaT wprlBtri hfh

15、rp如果使用标准 C库而调用VC运行时库函数,则在程序的 link阶段会提示如下错误:error LNK2001: unresolved external symbol _endthreadex error LNK2001: unresolved external symbol _beginthreadex清单3-2的程序中是读者写者问题的一个实现, 满足读者优先原则, 使用同步机制的互斥量实现,对每个读者和写者分别用一个线程来表示。测试数据文件的数据格式说明:测试数据文件包括n行测试数据,每行描述创建的是用于产生读者还是写者的数据。 行测试数据包括 4个字段,各字段间用空格分隔。第一字段为线

16、程序号。第二字段表示相应线程角色, W表示写者,R表示读者。第三字段为线程延迟。第四字段为线程读写操作持续时间。HANDLE RP_Write;等待互斥变量所有权/延迟时间/读文件持续时间/线程序号unsigned int _stdcall RP_ReaderThread(void *p) -/互斥变量HANDLE h_Mutex;h_Mutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,mutex_for_readcount);DWORD wait_for_mutex;DWORD m_delay;DWORD m_persist;int m_serial;/从参数中

17、获得信息m_serial = (Threadinfo *)(p)-serial;m_delay = (DWORD)(ThreadInfo *)(p)-delay*INTE_PER_SEC); m_persist = (DWORD)(ThreadInfo*)(p)-persist*INTE_PER_SEC); Sleep (m_delay) ; / 延迟等待printf(Reader thread %d sents the reading require n,m_serial);/等待互斥信号,保证对 readcount 的访问、修改互斥 wait_for_mutex = WaitForSing

18、leObject(h_Mutex,-1);/ 读者数目增加 readcount+; if(readcount =1)/ 这是第一个读者,第二个读者到来时, readcount 为 2,if 的条件不满足, 不会进入 if 语句内部 执行/这是第一个读者,如果此刻没有写者正在写,则 RP_Write 信号量状态为可用(未占用) ,那它就必须先占用(锁定) RP_Write 信号量,这就实现了读 -写互斥/如果此刻有写者正在写,则 RP_Write 信号量被写者占用(锁定) ,读者想对 RP_Write 加锁就 会阻塞在此,等待 RP_Write 信号量释放后,才能继续运行WaitForSingl

19、eObject(RP_Write, INFINITE);ReleaseMutex(h_Mutex) ; /释放互斥信号/ 读文件printf(Reader thread %d begins to read file.n,m_serial);Sleep(m_persist) ;/ 退出线程printf(Reader thread %d finished reading file.n,m_serial);/等待互斥信号,保证对 readcount 的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex,-1) ;/读者数目减少readcount-

20、; if(readcount = 0) /如果所有读者读完,则释放 RP_Write 信号量;此刻若有写者正在等待(处于阻塞状态) ,将(自动)唤醒写者ReleaseMutex(RP_Write);ReleaseMutex(h_Mutex) ; /释放互斥信号return 0; / 读者优先写者线程/ p:写者线程信息unsigned int _stdcall RP_WriterThread(void* p)DWORD m_delay; /延迟时间DWORD m_persist; /写文件持续时间int m_serial; /线程序号/从参数中获得信息m_serial = (ThreadInf

21、o *)(p)-serial;m_delay = (DWORD)(ThreadInfo *)(p)-delay*INTE_PER_SEC) ; m_persist = (DWORD)(ThreadInfo *)(p)-persist*INTE_PER_SEC) ;Sleep (m_delay); /延迟等待printf(Writer thread %d sents the writing require.n,m_serial);/ 写者在进行写数据之前,必须确定没有其它写者正在写,也没有其它读者在读,/ 通 过 RP_Write 互 斥 量 实 现 , 若 有 其 它 写 者 正 在 写 或

22、其 它 读 者 在 读 , 则 该 写 者 调 用 “ WaitForSingleObject(RP_Write, INFINITE); ”后将阻塞在此/ 等待 RP_Write 信号量释放后,才能够继续向下执行。WaitForSingleObject(RP_Write, INFINITE);/ 写文件printf(Writer thread %d begins to write to the file.n,m_serial);Sleep(m_persist) ;/ 退出线程printf(Writer thread %d finished writing to the file.n,m_ser

23、ial);/写者写完后,需要释放 RP_Write 信号量资源 ReleaseMutex(RP_Write);return 0; / 读者优先处理函数/ file :文件名void ReaderPriority(char *file)int i;DWORD n_thread = 0; / 线程数目UINT thread_ID; / 线程 IDDWORD wait_for_all; / 等待所有线程结束/ 互斥对象HANDLE h_Mutex;h_Mutex = CreateMutex(NULL,FALSE,mutex_for_readcount);/ 线程对象的数组HANDLE h_Threa

24、dMAX_THREAD_NUM ;ThreadInfo thread_infoMAX_THREAD_NUM ;readcount = 0 ; / 初始化 readcounttRP_Write = CreateMutex(NULL, FALSE, NULL); / 初始化用于读 -写互斥、写 -写互斥的信号量ifstream inFile; / 打开文件inFile.open(file) ;printf(Reader Priority:nn) ;while(inFile)/读人每一个读者、写者的信息 inFilethread_infon_thread.serial ;inFilethread_i

25、nfon_thread.entity;inFilethread_infon_thread.delay; inFilethread_infon_thread+.persist;inFile.get();for(i = 0; i (int)(n_thread); i+)if(thread_infoi.entity = READER | thread_infoi.entity = r)/ 创建读者线程h_Threadi = (HANDLE)_beginthreadex(NULL, 0, RP_ReaderThread, &thread_infoi, 0, &thread_ID);else / 创建写

26、者线程h_Threadi = (HANDLE)_beginthreadex(NULL, 0, RP_WriterThread, &thread_infoi, 0,&thread_ID);/等待所有线程结束wait_for_all = WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1) ; printf(All reader and writer have finished operating.n);/关闭线程句柄,关闭信号量句柄for(i = 0; i (int)(n_thread); i+) CloseHandle(h_Threadi); CloseHandle(h_Mutex);CloseHandle(RP_Write);/主函数 int main(int argc, char* argv)char ch;while ( true )printf( 1: Reader Priorityn) ;printf( 2: Exit to Windowsn) ;printf( * printf( Enter your choice (1 or 2): );/如果输入信息不正确,继续输入 doch = (char)_getch() ; while(c

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1