分享

Untitled Document

 ShangShujie 2007-04-01
同步问题 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 Explicit
            Const INFINITE = &HFFFF
            Const ERROR_ALREADY_EXISTS = 183&
            Const WAIT_TIMEOUT = &H102
            Const WAIT_ABANDONED = &H80
            Const WAIT_OBJECT_0 = 0
            Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
            Private Declare Function OpenMutex Lib "kernel32" Alias "OpenMutexA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long
            Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As Long
            Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
            Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
            Private Declare Function GetLastError Lib "kernel32" () As Long
            Private hMutex As Long
            Private m_TimeOut As Long
            Private m_Owner As Long
            ‘传回值 1 :Create成功  0:表Mutex已Create过了 -1表失败
            Public Function Create(ByVal muName As String) As Long
            If muName = "" Then
            Create = -1
            Exit Function
            End If
            If hMutex <> 0 Then
            Create = 0
            Exit Function
            End If
            hMutex = CreateMutex(ByVal 0, m_Owner, muName)
            If hMutex <> 0 Then
            Create = 1
            End If
            End Function
            ‘1表成功   0为失败
            Public Function ReleaseOwnerShip() As Long
            ReleaseOwnerShip = ReleaseMutex(hMutex)
            End Function
            ‘传回值 1: 表已Single  0:timeout  -1:有误
            Public Function GetOwnerShip() As Long
            Dim i As Long
            If 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 If
            Else
            GetOwnerShip = -1
            End If
            End Function
            Private Sub Class_Initialize()
            hMutex = 0
            m_TimeOut = INFINITE
            m_Owner = 0
            End Sub
            Private Sub Class_Terminate()
            Call ReleaseOwnerShip
            Call CloseHandle(hMutex)
            End Sub
            Public Property Get TimeOut() As Long
            TimeOut = m_TimeOut
            End Property
            Public Property Let TimeOut(ByVal vNewValue As Long)
            If vNewValue < 0 Then
            vNewValue = 0
            End If
            m_TimeOut = vNewValue
            End Property
            Public Property Get CreateWithOwnerShip() As Boolean
            If m_Owner = 0 Then
            CreateWithOwnerShip = False
            Else
            CreateWithOwnerShip = True
            End If
            End Property
            Public Property Let CreateWithOwnerShip(ByVal vNewValue As Boolean)
            If CreateWithOwnerShip Then
            m_Owner = 1
            Else
            m_Owner = 0
            End If
            End Property
            

以下在form需三个Command button, 一个label
Option Explicit
            Private mtx As New TMutex
            Private Sub Command1_Click()
            Dim i As Long
            i = mtx.Create("MutexX")
            mtx.TimeOut = 10000
            End Sub
            Private Sub Command2_Click()
            Dim i As Long
            i = mtx.GetOwnerShip
            If i = 1 Then
            Label1.Caption = "Now I am the Owner of the Mutex"
            Else
            Label1.Caption = "Fail to get OwnerShip"
            End If
            End Sub
            Private Sub Command3_Click()
            mtx.ReleaseOwnerShip
            End Sub
            


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多