看孙鑫老师VC++视频教程笔记 之 多线程编程(二)

一、线程的同步

         创建互斥对象完成线程同步 :      

    HANDLE CreateMutex(
      LPSECURITY_ATTRIBUTES lpMutexAttributes,
      BOOL bInitialOwner,
      LPCTSTR lpName
    );
    打开一个命名的或者没有名字的互斥对象:
    参数1:指向SECURITY_ATTRIBUTES结构体的指针。可以传递NULL,让其使用默认的安全性。
    参数2:指示互斥对象的初始拥有者。如果该值是真,调用者创建互斥对象,调用的线程获得互斥对象
          的所有权。否则,调用线程捕获的互斥对象的所有权。(就是说,如果该参数为真,则调用
          该函数的线程拥有互斥对象的所有权。否则,不拥有所有权)
    参数3:互斥对象名称。传递NULL创建的就是没有名字的互斥对象,即匿名的互斥对象。
   返回值:如果函数成功,返回Mutex对象的一个句柄。如果命名的互斥对象在调用函数前已经存在,
          函数返回已经存在的互斥对象的句柄,然后调用GetLastError返回ERROR_ALREADY_EXISTS。
          否则,调用者创建互斥对象。
   例://创建匿名互斥对象
      //当前没有线程拥有互斥对象,操作系统会将互斥对象设置为已通知状态(有信号状态)
       HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
   另:关于互斥对象
    *互斥对象(Mutex)属于内核对象,它能确保线程拥有对单个资源的互斥访问权。
    *互斥对象包含一个使用数量,一个线程ID(哪个线程拥有互斥对象,就设置为哪个线程的线程ID)和一个计数器。
    *ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。    
二、在线程中请求互斥对象 
    DWORD WaitForSingleObject(
      HANDLE hHandle,
      DWORD dwMilliseconds
    );
    出现下面情况之一时返回:
    1、指定的对象处于有信号状态;
    2、超出了超时(time-out)的时间间隔。
 
    参数1:对象的句柄,这里传递的是互斥对象的句柄。一旦互斥对象变成有信号状态,该函数返回。
          如果互斥对象始终没有处于有信号状态(非信号状态),函数将一直处于等待,导致线程
          暂停运行。
    
    参数2:指定超时的时间间隔,以毫秒为单位。
          如果时间间隔流逝了,函数就返回,即使等待的互斥对象处于非信号状态;
          如果将该参数设置为0,该函数测试对象的状态然后立即返回;
          如果将该参数设置为INFINITE,函数的超时值永远不会发生,也就是说函数将永远等待,直到
          所等待的对象处于有信号状态。
 
 
    注意:可以在我们需要保护的代码前面加上WaitForSingleObject(),当我们请求互斥对象的时候
         操作系统会判断请求互斥对象的线程和拥有互斥对象的线程的ID是否相等,如果相等,即使
         互斥对象处于未通知状态(非信号状态),仍然能够获得互斥对象的所有权。操作系统通过
         互斥对象的计数器记录请求了多少次互斥对象。
         另:可通过该函数的返回值,得知如何获得的互斥对象所有权。
 
    
   例://除非等待的互斥对象变为有信号状态,才继续运行,否则永远等待
         WaitForSingleObject(hMutex, INFINITE);
       //如果互斥对象处于有信号状态(已通知状态)则得到互斥对象,并将互斥对象设置为
       //未通知状态(非信号状态),然后继续运行。
 
三、释放互斥对象
    释放互斥对象,使互斥对象处于已通知状态(有信号状态):
    BOOL ReleaseMutex(
      HANDLE hMutex
    );
    释放指定互斥对象的所有权。如果成功返回非0值,失败返回0。
    
    在需要保护的代码后调用ReleaseMutex释放互斥对象,操作系统会将互斥对象的线程ID设置为0,
    
    并将互斥对象设置为已通知状态(有信号状态)。同时,互斥对象的计数器减一。
    
   注意:调用该函数的时候,操作系统会判断调用线程ID与互斥对象内部所维护的线程ID号是否相等,如果
         不等,互斥对象就不能被释放。
   释放互斥对象的原则:谁拥有,谁释放。
       
四、调用的形式
    //在主线程中
    ...
    HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
    ...
    //其他线程中
    
    ...
    WaitForSingleObject(hMutex, INFINITE);
    
    //受保护的代码
    ...
    ReleaseMutex(hMutex);
    
五、互斥对象的一个应用
    //避免同一程序运行多次
    hMutex = CreateMutex(NULL, FALSE, "mutex");
    if (hMutex)
    {
        if ( ERROR_ALREADY_EXISTS == GetLastError() )
        {
            cout<<"仅可以运行一个实例!"<<endl;
            return;
         }
     }

                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值