VC线程同步(互斥对象Mutex)及资源共享....

来源:互联网 发布:物流抢单软件 编辑:程序博客网 时间:2024/05/24 05:48

由于主线程中定义的变量,在所有子线程都可共享,这样便带来一个问题----由于线程的同步实际是通过给每个线程一个很小的时间片,轮流执行而并不是一个线程执行完成再来执行另一个线程来实现的,如果在执行的过程中几个线程都用到了一个共享变量,此时每个线程都有可能改变这个变量,这样做是不安全的,在一个线程中变量不变或者自已内部改变直到线程结束才是安全的。

 

如何避免这种不安全的访问共享资源的问题出现呢?

 

1、通过互斥对象实现线程同步,互斥对象包含三个变量:使用数量、线程ID、计数器。

    其中线程ID标明了是哪个线程当前拥有这个互斥对象,计数器用于指明该线程拥有互斥对象的次数。

 

   互斥对象的创建:

  HANDLE CreateMutex(
         LPSECURITY_ATTRIBUTES
 lpMutexAttributes,
                      
 // pointer to security attributes
        
 BOOL bInitialOwner // flag for initial ownership
        
 LPCTSTR lpName       // pointer to mutex-object name
         );

      第一个参数可以设置为NULL,即采用默认的安全性访问。

       第二个参数指明互斥对象的拥有者。如果此值为TRUE表明创建这个互斥对象的的线程获得该对象的所

       有权。否则当前没有线程拥有该互斥对象,此时在需要的地方就应该调用WaitForSingleObject申请

      拥有权.

       第三个参数为互斥对象的名称。如果为NULL表示创建了一个匿名的互斥对象。

      可以调用GetLastError()函数,看其返回值是否为ERROR_ALREADY_EXISTS,如果是则表明该互斥对象已经存在了。

 

 

       当一个线程对共享资源访问结束后,应该释放该对象的所有权。

       BOOLReleaseMutex(
             HANDLE
 hMutex   // handle tomutex object
            );

      

      一个线程如果想要获得共享对象的使用权则必须要主动申请才有可能获得。

      DWORDWaitForSingleObject(
             HANDLE
 hHandle,        // handle toobject to wait for
             DWORD dwMilliseconds   // time-outinterval in milliseconds
             );
       
 dwMilliseconds表示等待的时间间隔。以ms为单位。如果指定的时间间隔已过,即使所请求的对象仍处

    于无信号状态,WaitForSingleObject函数也会返回。如果将此参数设置为0,那么

WaitForSingleObject函数将测试该对象的状态并立即返回;如果将此参数设置为INFINITE,则该函

        数会永远等待,直到等待的对象处于有信号状态才会返回。

        程序中调用WaitForSingleObject后,该函数会一直等待,只有在两种情况下才会返回:

       1)指定的对象变成有信号状态。

       2)指定的等待时间间隔已过。

       如果该函数返回,则返回值表明引起该函数返回的事件,以下为可能的返回值

       WAIT_OBJECT_0   所请求的对象是有信号状态(就是指当前没有线程拥有该互斥对象)

       WAIT_TIMEOUT    指定的时间间隔已过,并且所请求的对象是无信号状态。

       WAIT_ABANDONED  所请求的对象是一个互斥对象,并且先前拥有该对象的线程在终止前没有释放该对

               象。这时,该对象的所有权将授予当前调用线程,并且将该互斥对象被设置为无信号的状态。

 

由以上可见,要想用到互斥对象则首先要创建一个所有有关线程共有的互斥对象,之后在每个相关的线程中在调用共享数据时调用WaitForSingleObject函数,保证访问的安全。在用完共享资源时用ReleaseMutex释放互斥对象。如果当一个线程拥有了互斥对象的所有权后,没有调用ReleaseMutex释放所有权,则其它的线程将永远无法获得该互斥对象的所有权。

 

需要特别注意的一点,即在创建互斥对象的时候如果第二个参数设置为TRUE时,表明创建该对象的线程拥有互斥对象的所有权,在该线程中一定要有一个释放该拥有权即要有ReleaseMutex函数,或者其它的线程将永远无法获得拥有权。同时如果创建之初设置为TRUE后,如果之后就调用了申请拥有权的函数WaitForSingleObject,则此时这个线程就要调用两次ReleaseMutex才能释放掉拥有权否则其它的线程也永远无法获得所有权,因为设置为TRUE创建之后,里面有一个互斥对象计数器将加1,并记录下拥有者的线程ID,当调用WaitForSingleObject函数后,互斥对象首先判断,拥有者ID与申请者的线程ID是否相等,如果相等即使此时互斥对象标明的是无信号状态,但计数器还是会再次加1变为2,当你调用一次

ReleaseMutex后,计数器减1,计数器值为1,表明了互斥对象还被一个线程拥有着,故其它线程将无法获得拥有权,直到拥有者再次调用ReleaseMutex之后,将计数器值变为0,才表明互斥对象没有被任何线程所拥有,其它线程才有可能拥有所有权。

原创粉丝点击