Mutex的使用

来源:互联网 发布:mac office用户名修改 编辑:程序博客网 时间:2024/04/28 10:00
同步问题 Mutex的使用来源:cww请先看   htmapi72.htm--"同步问题 Event的使用"
如同使用Event的文章所述,如果两个以上的Thread,同时想修改数个共用的记忆体,那我们要保证同时之间,只有一个Thread可做Update的动作,而且要等该Thread完成所有修改後,其他的Thread才可以读取或修改;这便要使用Mutex物件的技术了。Mutex的作法可以想像,大家都想做某件事前,要先取得一个许可金牌才能做,等做完了才将这金牌Release出来,其他人只能一直等,直到取得金牌的拥有权後,方能做事。Mutex物件的做法与特性如下:使用CreateMutex()来产生一个Mutex物件,而传入的Mutex名称字串用以区别不同的Mutex,也就是说,不管是哪个Process/Thread,只要传入的名称叁数是相同的一个字串,那CreateMutex()传回值(hMutex, handle of Mutex)会指向相同的一个Mutex物件。这和Event物件相同。然而Mutex和Event有很大的不同,Mutex有Owner的概念,如果Mutex为ThreadA所拥有,那麽ThreadA执行WaitForSingleObject()时,并不会停下来,而会立即传回WAIT_OBJECT_0,而其他的Thread执行WaitForSingleObject()则会停下来,直到Mutex的所有权被Release出来或Time Out。而Thread如何取得Mutex的所有权呢?主要如下: 1.CreateMutex(Byval 0, 1, "MyMutex") 第二个叁数传1进去,则第一个呼叫CreateMutex 且第二个叁数传1的Thread会拥有该Mutex。但如果第二个叁数传0进去,那代表 CreateMutex时,没有人拥有该Mutex。 2.承上的说明,如果Mutex没有拥有者,则第一个呼叫WaitForSingleObject的Thread 会拥有该Mutex。上面说过,只有拥有该Mutex的Thread在执行WaitForSingleObject()不会停下来,其他的Thread则会停下来,那其他的Thread如何取得该Mutex的所有权呢?那必需是原先拥有该Mutex的Thread以ReleaseMutex来放弃所有权,一旦所有权放出来,而有其他的Thread处於WaitForSingleObject()的停留等待状态,则有一个Thread会即时取得该Mutex的所有权(上面第2点的说明),所以,若其他的Thread也执行WaitForSingleObject()时,就会处於等待的状态。正因WaitForSingleObject()会令Mutex处於UnSignal的状态(和Event不同),所以可以完成同一时问只有一个thread来UpDate共用记忆体的需求(当然大家都要使用Mutex的规则则来做,即想Update时,要使用WaitForSingleObject()来看看是否可取得Mutex的所有权。)另有一件事要特别提出,如果一个Thread已取得Mutex的所有权,而它呼叫WaitForSingleObject()n 次,则也要使用ReleaseMutex n次才能够将Mutex的拥有权放弃,这和Event也不同,而且,非Mutex拥有者呼叫ReleaseMutex也不会有任何作用。而每次以WaitForSingleObject呼叫一次,Mutex会有一个计数器会加一,ReleaseMutex成功会减一,直到Mutex的计数器为0之後,系统才会将之去除。以下用一个Class来做Mutex方法 Create(ByVal MutexName As String) 传入Mutex的识别名称,如果成功传回1,已Create过传回0,失败传回-1 GetOwnerShip()传回值 1: 表已取得所有权 0:timeout -1:有误 ReleaseOwnerShip()传回值 1表ReleaseMutex成功 0失败属性 TimeOut 要GetOwnerShip时Time Out的时间,千分之一秒为单位 CreateWithOwnerShip true表Create时,就顺带取得Mutex的所有权以下的程式请用两个执行个体(两份相同的VB程式)来试验才能显示效果以下在Mutex.Cls, class name: TMutex
Option ExplicitConst INFINITE = &HFFFFConst ERROR_ALREADY_EXISTS = 183&Const WAIT_TIMEOUT = &H102Const WAIT_ABANDONED = &H80Const WAIT_OBJECT_0 = 0Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As LongPrivate Declare Function OpenMutex Lib "kernel32" Alias "OpenMutexA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As LongPrivate Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As LongPrivate Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As LongPrivate Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPrivate Declare Function GetLastError Lib "kernel32" () As LongPrivate hMutex As LongPrivate m_TimeOut As LongPrivate m_Owner As Long'传回值 1 :Create成功  0:表Mutex已Create过了 -1表失败Public Function Create(ByVal muName As String) As LongIf muName = "" Then   Create = -1   Exit FunctionEnd IfIf hMutex <> 0 Then   Create = 0   Exit FunctionEnd IfhMutex = CreateMutex(ByVal 0, m_Owner, muName)If hMutex <> 0 Then   Create = 1End IfEnd Function'1表成功   0为失败Public Function ReleaseOwnerShip() As Long   ReleaseOwnerShip = ReleaseMutex(hMutex)End Function'传回值 1: 表已Single  0:timeout  -1:有误Public Function GetOwnerShip() As LongDim i As LongIf hMutex <> 0 Then   i = WaitForSingleObject(hMutex, m_TimeOut)   '如果原先拥有Mutex的thread有ReleaseMutex则传回WAIT_OBJECT_0   '如果没有ReleaseMutex便被Terminate,则传回WAIT_ABANDONED   If i = WAIT_OBJECT_0 Or i = WAIT_ABANDONED Then      GetOwnerShip = 1   Else      If i = WAIT_TIMEOUT Then GetOwnerShip = 0      Else GetOwnerShip = -1      End If   End IfElse  GetOwnerShip = -1End IfEnd FunctionPrivate Sub Class_Initialize()hMutex = 0m_TimeOut = INFINITEm_Owner = 0End SubPrivate Sub Class_Terminate()Call ReleaseOwnerShipCall CloseHandle(hMutex)End SubPublic Property Get TimeOut() As LongTimeOut = m_TimeOutEnd PropertyPublic Property Let TimeOut(ByVal vNewValue As Long)If vNewValue < 0 Then   vNewValue = 0End Ifm_TimeOut = vNewValueEnd PropertyPublic Property Get CreateWithOwnerShip() As BooleanIf m_Owner = 0 Then   CreateWithOwnerShip = FalseElse   CreateWithOwnerShip = TrueEnd IfEnd PropertyPublic Property Let CreateWithOwnerShip(ByVal vNewValue As Boolean)If CreateWithOwnerShip Then   m_Owner = 1Else   m_Owner = 0End IfEnd Property

以下在form需三个Command button, 一个label
Option ExplicitPrivate mtx As New TMutexPrivate Sub Command1_Click()Dim i As Longi = mtx.Create("MutexX")mtx.TimeOut = 10000End SubPrivate Sub Command2_Click()Dim i As Longi = mtx.GetOwnerShipIf i = 1 Then   Label1.Caption = "Now I am the Owner of the Mutex"Else   Label1.Caption = "Fail to get OwnerShip"End IfEnd SubPrivate Sub Command3_Click()mtx.ReleaseOwnerShipEnd Sub