zoukankan      html  css  js  c++  java
  • 零基础逆向工程36_Win32_10_互斥体_互斥体与临界区的区别

    1 引言

    讲了第二个内核对象,互斥体。前面已经学过一个内核对象,线程。这节讲两个函数,WaitForSingleObject()和WaitForMultipleObjects()。因此这两个函数是根据内核对象的状态来进行操作的。

    临界区:一个进程里面对线程进行互斥的控制。
    互斥体:实现跨进程的互斥的控制。多个进程抢同一个全局变量,怎样保证最终只有一个进程来用。

    2 ForSingleObject()

    DWORD WaitForSingleObject(
      HANDLE hHandle,        // handle to object
      DWORD dwMilliseconds   // time-out interval
    );
    
    

    功能说明:
    等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止.

    hHandle:
    内核对象句柄,可以是进程也可以是线程.

    dwMilliseconds:
    等待时间,单位是毫秒 INFINITE(-1)一直等待

    返回值:
    WAIT_OBJECT_0(0) 等待对象变为已通知
    WAIT_TIMEOUT(0x102) 超时

    特别说明:
    1、内核对象中的每种对象都可以说是处于已通知或未通知的状态之中
    2、这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的
    3、当线程正在运行的时候,线程内核对象处于未通知状态
    4、当线程终止运行的时候,它就变为已通知状态
    5、在内核中就是个BOOL值,运行时FALSE 结束TRUE

    代码演示

    DWORD WINAPI ThreadProc1(LPVOID lpParameter)    
    {     
       for(int i=0;i<5;i++) 
       {  
          printf("+++++++++
    ");
          Sleep(1000);
       }  
       return 0;   
    }     
          
    int main(int argc, char* argv[])    
    {     
          
       //创建一个新的线程  
       HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,   
          NULL, 0, NULL);
          
       DWORD dwCode = ::WaitForSingleObject(hThread1, INFINITE);   
          
       MessageBox(0,0,0,0); 
          
       return 0;   
    }     
    
    

    3 和WaitForMultipleObjects()

    DWORD WaitForMultipleObjects(
      DWORD nCount,             // number of handles in array
      CONST HANDLE *lpHandles,  // object-handle array
      BOOL bWaitAll,            // wait option
      DWORD dwMilliseconds      // time-out interval
    );
    
    

    功能说明:同时查看若干个内核对象的已通知状态

    nCount:要查看内核对象的数量

    lpHandles:内核对象数组

    bWaitAll:等到类型 TRUE 等到所有变为已通知 FALSE 只要有一个变为已通知

    dwMilliseconds:超时时间

    INFINITE一直等待

    返回值:
    bWaitAll为TRUE时,返回WAIT_OBJECT_0(0) 代码所以内核对象都变成已通知
    bWaitAll为FALSE时,返回最先变成已通知的内核对象在数组中的索引

    WAIT_TIMEOUT(0x102)

    代码演示:

    DWORD WINAPI ThreadProc1(LPVOID lpParameter)    
    {     
       for(int i=0;i<5;i++) 
       {  
          printf("+++++++++
    ");
          Sleep(1000);
       }  
       return 0;   
    }     
          
    DWORD WINAPI ThreadProc2(LPVOID lpParameter)    
    {     
       for(int i=0;i<3;i++) 
       {  
          printf("---------
    ");
          Sleep(1000);
       }  
          
       return 0;   
    }     
          
          
    int main(int argc, char* argv[])    
    {     
          
       HANDLE hArray[2]; 
          
       //创建一个新的线程  
       HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,   
          NULL, 0, NULL);
          
       //创建一个新的线程  
       HANDLE hThread2 = ::CreateThread(NULL, 0, ThreadProc2,   
          NULL, 0, NULL);
          
       hArray[0] = hThread1;   
       hArray[1] = hThread2;   
          
       DWORD dwCode = ::WaitForMultipleObjects(2, hArray,FALSE,INFINITE);   
          
       MessageBox(0,0,0,0); 
          
       return 0;   
    }     
    

    4 跨进程的线程控制与互斥体

    进程一:
    HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");

    进程二:
    HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
    WaitForSingleObject(g_hMutex,INFINITE);

    //逻辑代码
    ReleaseMutex(g_hMutex);

    进程三:
    HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
    WaitForSingleObject(g_hMutex,INFINITE);

    //逻辑代码
    ReleaseMutex(g_hMutex);

    互斥体与临界区的区别:
    1、临界区只能用于单个进程间的线程控制.
    2、互斥体可以设定等待超时,但临界区不能.
    3、线程意外终结时,Mutex可以避免无限等待.
    4、Mutex效率没有临界区高.

    5 练习项目

    做一个抢红包项目,要求如下

    第一步:在第一个文本框中输入一个值,比如1000         
    第二步:点击抢红包,同时创建3个线程,每个线程循环进行抢红包的操作,每次抢50    
    第三步:使用Mutex进行线程控制,当第一个文本框中的值<50时,强红包线程结束.       
    特别说明:        
    1、四个文本框中的值总和应该为1000  
    2、强红包线程每次延时50毫秒. 
    3、使用WaitForMultipleObjects监听所有线程,当线程全部结束后       
       调用CloseHandle关闭句柄. 
    
  • 相关阅读:
    Integer to Roman leetcode java
    Reverse Integer leetcode java
    Binary Tree Maximum Path Sum leetcode java
    公司来了一个奇葩需求pppoe client+server+EOIP+vlan
    魔兽数据库-自然
    windows默认dns解析走ipv4而不走ipv6
    ROS支持BCP桥接(基于PPP隧道)
    几款比较好用的电动理发器推荐
    centos 拨号pptp在拨号成功和拨号失败的时候脚本处理!!!非常重要
    ros routeros 脚本命令script
  • 原文地址:https://www.cnblogs.com/flatcc/p/7859302.html
Copyright © 2011-2022 走看看