欢迎来到冰点文库! | 帮助中心 分享价值,成长自我!
冰点文库
全部分类
  • 临时分类>
  • IT计算机>
  • 经管营销>
  • 医药卫生>
  • 自然科学>
  • 农林牧渔>
  • 人文社科>
  • 工程科技>
  • PPT模板>
  • 求职职场>
  • 解决方案>
  • 总结汇报>
  • ImageVerifierCode 换一换
    首页 冰点文库 > 资源分类 > DOCX文档下载
    分享到微信 分享到微博 分享到QQ空间

    网络编程技术实验2Windows线程同步和互斥解析.docx

    • 资源ID:9512155       资源大小:21.34KB        全文页数:16页
    • 资源格式: DOCX        下载积分:3金币
    快捷下载 游客一键下载
    账号登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录
    二维码
    微信扫一扫登录
    下载资源需要3金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP,免费下载
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    网络编程技术实验2Windows线程同步和互斥解析.docx

    1、网络编程技术实验2Windows线程同步和互斥解析实验2 Windows线程同步和互斥实验目的1、了解Windows内核对线程同步的支持。2、了解C的线程函数库及Windows 基本的线程API 函数的使用。3、进一步理解线程的同步控制原理。预备知识一、Windows线程同步机制(注:互斥是同步的一种特例)事件(Event)临界区(Critical Section)互斥量(Mutex)信号量(Semaphore)1、是否能跨进程使用?互斥量、信号量、事件都可以跨进程来实现同步数据操作。临界区只能用在同一进程的线程间互斥,因为临界区无名(无句柄)。如果只为了在进程内部用的话,使用临界区会带来速度

    2、上的优势并能够减少资源占用量。2、其它区别临界区:访问临界资源的代码段。课堂上讲过。(存钱、取钱的例子还记得吗?)互斥量:资源独占使用信号量:资源计数器事件对象:可以通过“通知”的方式来保持线程的同步。事件是WIN32中最灵活的线程间同步机制。事件存在两种状态:激发状态(Signaled or True)未激发状态(Unsignaled or False)。3、详细解释:(见下面实验内容每个程序前)二、VC+(略)实验内容1、用事件(Event)对象来进行线程同步事件可分为两类:手动设置: 这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进

    3、行设置。自动恢复: 一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。_beginthread函数:创建一个线程。所在库文件:#include uintptr_t _beginthread( void( *start_address )( void * ), unsigned stack_size, void *arglist ); 返回值: 假如成功,函数将返回一个处理信息对这个新创建的线程。如果失败_beginthread将返回-1。 start_address 新线程的起始地址 ,指向新线程调用的函数的起始地址stack_size stack_size 新线程的堆栈大小,可

    4、以为0arglist arglist 传递给线程的参数列表,无参数是为NULL CreateEvent函数:创建事件对象 windows.hHANDLE CreateEvent( / SECURITY_ATTRIBUTES结构指针,可为NULLLPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, / 手动/自动 / TRUE:在WaitForSingleObject后必须手动调用ResetEvent清除信号 / FALSE:在WaitForSingleObject后,系统自动清除事件信号 BOOL bInitialState,

    5、/初始状态 LPCTSTR lpName /事件的名称);使用“事件”机制应注意以下事项:如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;事件是否要自动恢复;事件的初始状态设置。由于event对象属于内核对象,故进程B可以调用OpenEvent函数通过对象的名字获得进程A中event对象的句柄,然后将这个句柄用于ResetEvent、SetEvent和WaitForMultipleObjects等函数中。此法可以实现一个进程的线程控制另一进程中线程的运行,例如: HANDLE hEvent=OpenEvent(EVENT_ALL_ACC

    6、ESS,true,MyEvent); ResetEvent(hEvent);验证程序:3个线程。主线程创建2个线程。一读,一写。写线程(并不真写,只是输出writing等字符串)完成后,读线程才能读,读线程完成后,主线程才能结束。新建一个Win32控制台应用程序项目(win32 console application)#include stdafx.h#include #include #include #include HANDLE evRead,evFinish;/全局变量,事件对象的句柄void ReadThread(LPVOID param) WaitForSingleObject(e

    7、vRead, INFINITE);/等待evRead被激活 coutReading.读完成,唤醒主线程endl; SetEvent(evFinish);/激活evFinish事件void WriteThread(LPVOID param) coutWriting.写完成,唤醒读线程endl; SetEvent(evRead);/激活evRead事件int main(int argc, char* argv) evRead= CreateEvent(NULL,FALSE,FALSE,NULL); evFinish= CreateEvent(NULL,FALSE,FALSE,NULL); _beg

    8、inthread(ReadThread,0,NULL); _beginthread(WriteThread,0,NULL); WaitForSingleObject(evFinish, INFINITE);/等待evFinish被激活 coutEnd.endl; return 0;如果引入了,还有如下错误error C2065: _beginthread : undeclared identifierError executing cl.exe.解决:工程设置c/c+标签分类(Category)下拉列表里选择代码生成(Code Generation) 选用运行时库(Use Run-Time L

    9、ibrary)下拉列表里选择多线程Multithreaded。然后重新编译。若还不行,再选Multithreaded DLL。验证:用/将两条WaitForSingleObject语句屏蔽。重新编译运行,多运行几次,看结果有何不同。思考原因。2、用临界区(Critical Section)来进行线程互斥临界区是保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共

    10、享资源的目的。 临界区包含两个操作原语:EnterCriticalSection() 进入临界区 LeaveCriticalSection() 离开临界区 EnterCriticalSection()语句执行后代码将进入临界区以后无论发生什么,必须确保与之匹配的LeaveCriticalSection()都能够被执行到。否则,临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。 创建临界区为了创建临界区,首先必须在进程中分配一个全局CRITICAL_SECTION数据结构:CRITICAL_SECTION gCritic

    11、alSection;使用临界区使用临界区之前,必须调用InitializeCriticalSection函数初始化: VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);进入临界区调用EnterCriticalSection函数进入临界区:VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);离开临界区调用LeaveCriticalSection函数退出了临界区:VOID LeaveCriticalSection(LPCRITICAL_

    12、SECTION lpCriticalSection);删除临界区 调用DeleteCriticalSection函数删除临界区:VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);临界区一般用法:EnterCriticalSection(& gCriticalSection );/do somethingLeaveCriticalSection(& gCriticalSection);关于临界区的使用,有下列注意点:每个共享资源使用一个CRITICAL_SECTION变量;不要长时间运行关键代码段,当一个关键代码段长

    13、时间运行时,其他线程就会进入等待状态,这会降低应用程序的运行性能;如果需要同时访问多个资源,则可能连续调用EnterCriticalSection;Critical Section不是OS核心对象,如果进入临界区的线程挂了,将无法释放临界资源。这个缺点在Mutex中得到了弥补。验证程序:一个银行系统中两个线程对同一账户执行取款操作,余额1000元。一个使用ATM机取900元,另一个使用存折在柜台取700元。如果不加于控制,会使得账户余额为负数。#include stdafx.h#include #include #include #include int total =1000;HANDLE

    14、evFin2;CRITICAL_SECTION cs;void WithDrawThread1(LPVOID param) /取900元 EnterCriticalSection(&cs); if (total-900) = 0) total-=900; cout你取了900元 endl; else cout钱不够了,禁止取钱,马上退卡!= 0) total-=700; cout你取了700元 endl; else cout钱不够了,禁止取钱!endl; LeaveCriticalSection(&cs); SetEvent(evFin1);int main(int argc, char* a

    15、rgv) evFin0 = CreateEvent(NULL,FALSE,FALSE,NULL); evFin1 = CreateEvent(NULL,FALSE,FALSE,NULL); InitializeCriticalSection(&cs); _beginthread(WithDrawThread1,0,NULL); _beginthread(WithDrawThread2,0,NULL); WaitForMultipleObjects(2, evFin, TRUE, INFINITE); DeleteCriticalSection(&cs); cout余额是totalendl; r

    16、eturn 0;多运行几次,观察结果并分析。3、用互斥量(Mutex)来进行线程互斥互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限。由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。 用CreateMutex函数创建互斥量: HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMute

    17、xAttributes,/ 安全属性结构指针,可为NULLBOOL bInitialOwner, /是否占有该互斥量,TRUE:占有,FALSE:不占有LPCTSTR lpName /信号量的名称);涉及到的其它API如下:打开一个互斥量 :OpenMutex函数:HANDLE OpenMutex(DWORD fdwAccess,/ 值为SYNCHRONIZE或MUTEX_ALL_ACCESSBOOL fInherit,LPTSTR lpszName);释放一个互斥量 : ReleaseMutex函数:BOOL ReleaseMutex(HANDLE hMutex);该函数将互斥量从无信号状态

    18、变到有信号状态。互斥和临界区的比较如下图: 特性互斥临界区运行速度 慢 快 是否能够跨进程边界来使用 是 否 声明 HANDLE hmtx ; CRITICAL_SECTION cs ; 初始化 h m t x = C r e a t e M u t e x ( N U L L , FA L S E , N U L L ); I n i t i a l i z e C r i t i c a l S e c t i o n ( & e s ) ; 清除 C l o s e H a n d l e ( h m t x ); D e l e t e C r i t i c a l S e c t

    19、i o n ( & c s ); 无限等待 Wa i t F o r S i n g l e O b j e c t ( h m t x , I N F I N I T E ); E n t e r C r i t i c a l S e c t i o n ( & c s ); 0 等待 Wa i t F o r S i n g l e O b j e c t ( h m t x , 0 ); Tr y E n t e r C r i t i c a l S e c t i o n ( & c s ); 任意等待 Wa i t F o r S i n g l e O b j e c t (

    20、h m t x , d w M i l l i s e c o n d s ); 不能 释放 R e l e a s e M u t e x ( h m t x ); L e a v e C r i t i c a l S e c t i o n ( & c s ); 是否能够等待其他内核对象 是 (使用 Wa i t F o r M u l t i p l e O b j e c t s 或类似的函数) 否 验证程序:主线程创建3个线程。它们各自要输出一些字符串。#include stdafx.h#include #include #define THREAD_INSTANCE_NUMBER

    21、 3 /主线程要创建3个线程LONG g_RessourceInUse=FALSE;LONG g_iCounter=0;void ThreadProc(void *pData) int ThreadNumTemp=(*(int *) pData); HANDLE hMutex; coutThreadProc:ThreadNumTemp in Running!endl; if (hMutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,Mutex.Test)=NULL) coutOpen mutex error!endl; WaitForSingleObject(hMute

    22、x,INFINITE); coutThreadProc:ThreadNumTemp gets the mutex.endl; ReleaseMutex(hMutex); CloseHandle(hMutex); coutThreadProc:ThreadNumTemp end.endl;int main(int argc, char* argv) DWORD IDTHREAD_INSTANCE_NUMBER;/数组,存放3个线程的ID号码(CreateThread返回) HANDLE hTHREAD_INSTANCE_NUMBER;/数组,存放3个线程的句柄 HANDLE hMutex;/互斥

    23、量的句柄 int i; if (hMutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,Mutex.Test)=NULL) if (hMutex = CreateMutex(NULL,FALSE,Mutex.Test )= NULL) coutCreate Mutex error!endl; return 0; for (i=0;iTHREAD_INSTANCE_NUMBER;i+) hi=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,(void*)&IDi,0,&(IDi); if (hi=NULL) c

    24、out创建线程失败!endl; else cout创建线程成功 IDiendl; WaitForMultipleObjects(THREAD_INSTANCE_NUMBER,h,true,INFINITE); coutClose the mutex handle!endl; return 0;思考:输出多样,哪里体现了互斥量的作用?4、用信号量(Semaphore)来实现线程同步信号量是维护0到指定最大值之间的同步对象。信号量状态在其计数大于0时是有信号的,而其计数是0时是无信号的。信号量对象在控制上可以支持有限数量共享资源的访问。创建信号量: HANDLE CreateSemaphore (

    25、 PSECURITY_ATTRIBUTE psa, LONG lInitialCount, /开始时可供使用的资源数 LONG lMaximumCount, /最大资源数 PCTSTR pszName);撤销信号量:BOOL WINAPI ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount,/信号量的当前资源数增加lReleaseCount LPLONG lpPreviousCount); 打开信号量HANDLE OpenSemaphore ( DWORD fdwAccess, BOOL bInherithandle, PCTSTR

    26、pszName);验证程序:生产者与消费者问题。#include stdafx.h#include #include #define THREAD_INSTANCE_NUMBER 3#define PRODUCT_NUMBER 2#define MAX_ITEMS 2/ 定义信号量HANDLE m_S_Full; / SemaphoreHANDLE m_S_Empty; / SemaphoreHANDLE m_E_Mutex; / Eventint counter=0;void ThreadProducer(void *pData) /生产者 int j; int ThreadNumTemp=

    27、(*(int *) pData); for (j=0;jPRODUCT_NUMBER;j+) WaitForSingleObject(m_S_Empty, INFINITE); WaitForSingleObject(m_E_Mutex, INFINITE); / OK now, put product counter+; coutThreadProducer:ThreadNumTemp puts a porduct.endl; coutThreadProducer:ThreadNumTemp counter=counterendl; / relase comsumers semaphore

    28、ReleaseSemaphore(m_S_Full, 1, NULL); / set event to signal SetEvent(m_E_Mutex); void ThreadConsumer(void *pData) /消费者 int j; int ThreadNumTemp=(*(int *) pData); for (j=0;jPRODUCT_NUMBER;j+) WaitForSingleObject(m_S_Full, INFINITE); WaitForSingleObject(m_E_Mutex, INFINITE); / OK now, get a product counter-; coutThreadConsumer:ThreadNumTemp gets a porduct.endl; coutThreadConsumer:ThreadNumTemp counter=counterendl; / relase producers semaphore Releas


    注意事项

    本文(网络编程技术实验2Windows线程同步和互斥解析.docx)为本站会员主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    copyright@ 2008-2023 冰点文库 网站版权所有

    经营许可证编号:鄂ICP备19020893号-2


    收起
    展开