WIN32多线程程序设计学习笔记(第四章 上)

WIN32多线程程序设计学习笔记(第四章 上)
 
到目前为止,我已经知道如何创建线程,销毁线程及如何判断一个线程是否结束了;但运用线程,管理线程,如何使线程按自己意愿正确运行才是多线程程序设计的重点及难点。
 
大家知道,线程具有并发性,在同一时间段会存在多个线程,当这些线程同时存取同一数据时,就会有问题。就像在超市储物品一样,来的时候物品箱是空,转身拿物品准备储的时候,发现物品箱已被占用了。这时,物品箱就是我所说的同一数据,人指的就是线程了。
 
那么,如何让线程彼此互相合作,互不干扰呢?------协调线程的工作是由同步机制来完成的。正如书上所说:“有放多种同步机制可以运用。使用哪一种则完全视欲解决的问题而定。这些同步机制还能用各种方式组合在一起运用,以产生更精密的机制”。
 
首先,让我们看看最容易使用的一个同步机制;它包含同步机制的设计思想,拿握了它也就可以不费什么劲拿握其它的同步机制了。
1 Critical Sections( 关键区域、临界区域)
程序片段:
       CRITICAL_SECTION        gBoxKey ;
       DWORD WINAPI ThreadFun(LPVOID n)
       {
              // 进入关键区域 (情景:关上物品箱,拨下钥匙)
              EnterCreiticalSection (&gBoxKey ) ; (1
                     // 处理一些不可分割的操作。。。。。
                     // (情景:转身拿物品,储物品,去购物。。。。)
              // 离开关键区域 (情景:打开物品箱,拿出储存的物品,插上钥匙)                
              LeaveCreiticalSection (&gBoxKey) ; (2
       }
 
       void main()
       {
              // 初始化全局锁 ( 情景:生成物品箱的钥匙)
              InitializeCriticalSection( &gBoxKey ) ;             
              // 产生两个线程 ( 情景:准备两个人抢一个物品箱)
              HANDLE hMan1 = CreateThread(NULL,0,ThreadFun,…….);
              HANDLE hMan2 = CreateThread(NULL,0,ThreadFun,…….);
 
              CloseHandle(hMan1);
              CloseHandle(hMan2);
 
              // 删除全局锁 ( 情景:删除物品箱的钥匙)
              DeleteCriticalSection( &gBoxKey ) ;
       }
 
按照上面的程序,我在笔记开头所描述的“超市储物品”的情况是不会发生的,不会再有物品箱被人抢走的可能。由于线程的并发性,从我看到一个空箱子到我将物品的放入物品箱中的这段时间内的操作应该是不可分割的;否则,我看到的物品箱就随时会被人抢走。那么如何保证操作是连续、不可分割呢?简单:看到空箱子,关上箱子,拨下钥匙(1),这时,别人就没办法使用这个箱子了。当我不再需要箱子的时候,打开箱子,插入钥匙(2),就可以让别人使用了。上述就是多线程处理共享资源的一个基本思路。
 
2 Mutexes( 互斥器)
程序片段:
       HANDLE              hBoxKey ;
       DWORD WINAPI ThreadFun(LPVOID n)
       {
              // 进入关键区域 (情景:关上物品箱,拨下钥匙)
              WaitForSingleObject ( hMutex,INFINITE ) ; (1
                     // 处理一些不可分割的操作。。。。。
                     // (情景:转身拿物品,储物品,去购物。。。。)
              / 离开关键区域 (情景:打开物品箱,拿出储存的物品,插上钥匙)                
              ReleaseMutex ( hMutex ) ; (2
       }
 
       void main()
       {
              // 初始化全局锁 ( 情景:生成物品箱的钥匙)
              hBoxKey = CreateMutex(       NULL,FALSE,NULL );          
              // 产生两个线程 ( 情景:准备两个人抢一个物品箱)
              HANDLE hMan1 = CreateThread(NULL,0,ThreadFun,…….);
              HANDLE hMan2 = CreateThread(NULL,0,ThreadFun,…….);
 
              CloseHandle(hMan1);
              CloseHandle(hMan2);
 
              // 删除全局锁 ( 情景:删除物品箱的钥匙)
              CloseHandle( hBoxKey ) ;
       }
看到没?无论从共享资源的思路了,还是从程序代码的编制上,使用 Mutexes与使用 Critical Sections 几乎都没有什么区别;但作为 Mutexes 机制的提出肯定是有其原因的;我们来看这样的一个情形,当我拿走钥匙以后,因为某些因素再也不能回来了,那么这个箱子便再也不能被使用。也就是说,进入 Critical Sections 线程若中途当掉了,那么别了线程是再也进不了 Critical Sections ( 一个资源就这样浪费了 ) ,那些需要进入 Critical Sections 的线程会停在入口不再执行,线程永远都结束不了。
怎么办?( WaitForSingleObject 解决
还记得上一章学过的 WaitForSingleObject 吗?上一章主要用它等待线程的结束,但这个函数的作用不仅限于此,在这里,我们再前进一小步,探究 WaitForSingleObject 这个函数的妙用。
原型:
DWORD WaitForSingleObject ( HANDLE hObject DWORD  time ) ;
hObject :等待对象的 handle (代表一个核心对象) , 在上一章中代表线程 handle ,注意没有, hObject 代表一个核心对象 , 也就是说,只要是核心对象, WaitForSingleObject 都能处理 , 处理的原则是“ 当核心对象被激发时,函数返回 ”(有多少种核心对象 ? 及核心对象对 激发 的定义见 P76 )。
在这里,我遇到了一个叫 mutex 核心对象, mutex 对激发的定义是:“当没有 任何线程 拥有该mutex ,而且有一个线程 正以Wait…() 等待 mutex ,该mutex 就会短暂地出现激发状态, 使Wait…() 得以返回, 那么在其它的情况,mutex 处于未激发状态
 
好了,我们又进一步的了解了 WaitForSingleObject 函数,那么,如何解决 Critical Sections 所遇到的因难呢?当拥有 mutex 线程结束前 没有调用 ReleaseMutex (不管该线程是当了,还是忘记调用 ReleaseMutex ),那么其它正以 WaitForSingleObject() 等待此 mutex 的线程就会收到 WAIT_ABANDONED_0 。有了这个值,我就解开难题了。
程序片段:
DWORD        rc    =       WaitForSingleObject( hMutex ) ;
If ( rc  == WAIT_OBJECT_0 )
{
              // 正常的处理
}
else
{
              If ( rc  == WAIT_ABANDONED_0 )
{
                     // 没有正常的释放mutex (比如拥有mutex 的线程死了)
}
}
 
我想,从笔记的角度来看,上面对 mutex 描述已经可以帮助我很快的上手使用了,至于对 mutex 更详细的说明,还是要看看书 . ( 当然,希望我的这一段描述能帮助你理解 mutex J )
      
总结一下:
CRITICAL_SECTION                             Mutex 核心对象
 
InitializeCriticalSection()                                   CreateMutex()
                                                                      OpenMutex()
 
EnterCriticalSection()                                      WaitForSingleObject()
 
LeaveCriticalSection()                                      ReleaseMutex()
 
DeleteCriticalSection()                                    CloseHandle()
 
附注:以上正文纯属加强记忆所做笔记,内容或有不详,甚至错误,请阅者见谅,匆见怪!!!
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值