• window下线程同步之(Semaphores(信号量))----------------转载


    ---为转载内容

    复制代码
    HANDLE WINAPI CreateSemaphore( 
      _In_opt_  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes 
      _In_      LONG lInitialCount, 
      _In_      LONG lMaximumCount, 
      _In_opt_  LPCTSTR lpName 
    ); 
    复制代码

    第一个参数:安全属性,如果为NULL则是默认安全属性 
    第二个参数:信号量的初始值,要>=0且<=第三个参数 
    第三个参数:信号量的最大值 
    第四个参数:信号量的名称 
    返回值:指向信号量的句柄,如果创建的信号量和已有的信号量重名,那么返回已经存在的信号量句柄

    使用方法: 
    1、创建一个信号量:CreateSemaphore; 
    2、打开一个已经存在的信号量:OpenSemaphore; 
    3、获得信号量的一个占有权:WaitForSingleObject、WaitForMultipleObjects 等一类等待的函数……(可能造成阻塞); 
    4、释放信号量的占有权:ReleaseSemaphore; 
    5、关闭信号量:CloseHandle;

    ※ 命名标准:Semaphores 可以跨进程使用,所以其名称对整个系统而言是全局的,所以命名不要过于普通,类似:Semaphore、Object 等。 
    最好想一些独一无二的名字等!

    固有特点(优点+缺点): 
    1、是一个系统核心对象,所以有安全描述指针,用完了要 CloseHandle 关闭句柄,这些是内核对象的共同特征; 
    2、因为是核心对象,所以执行速度稍慢(当然只是相比较而言); 
    3、因为是核心对象,而且可以命名,所以可以跨进程使用; 
    4、Semaphore 使用正确的情况下不会发生死锁; 
    5、在“等待”一个 信号量 的时候,可以指定“结束等待”的时间长度; 
    6、非排他性的占有,跟 Critical Sections 和 Mutex 不同,这两种而言是排他性占有, 
    即:同一时间内只能有单一线程获得目标并拥有操作的权利,而 Semaphores 则不是这样, 
    同一时间内可以有多个线程获得目标并操作!

    信号量没有线程所有权属性,即一个线程获得某个信号量后,在他释放该信号量之前,他不能再次进入信号量保护的区域

    信号量的使用规则:

    1. 如果当前资源计数大于0,那么信号量处于触发状态;

    2. 如果当前资源计数等于0,那么信号量处于未触发状态;那么系统会让调用线程进入等待状态。

    CreateSemaphore(NULL,0,1,NULL); 当第二个参数为0时,调用线程就会进入等待状态

    3. 系统绝对不会让当前资源计数变为负数;

    4. 当前资源计数绝对不会大于最大资源计数。

    复制代码
    #include <iostream> 
    #include <windows.h> 
    using namespace std;
    
    const int g_Number = 3; 
    DWORD WINAPI ThreadProc1(__in  LPVOID lpParameter); 
    DWORD WINAPI ThreadProc2(__in  LPVOID lpParameter); 
    DWORD WINAPI ThreadProc3(__in  LPVOID lpParameter);
    
    HANDLE hSemp1,hSemp2,hSemp3;
    
    int main() 
    { 
       hSemp1 = CreateSemaphore(NULL,1,1,NULL); 
       hSemp2 = CreateSemaphore( NULL,1,1,NULL); 
       hSemp3 = CreateSemaphore(NULL,1,1,NULL);
    
        HANDLE hThread[ g_Number ] = {0}; 
        int first = 1, second = 2, third = 3; 
        hThread[ 0 ] = CreateThread(NULL,0,ThreadProc1,(LPVOID)first,0,NULL); 
        hThread[ 1 ] = CreateThread(NULL,0,ThreadProc2,(LPVOID)second,0,NULL); 
        hThread[ 2 ] = CreateThread(NULL,0,ThreadProc3,(LPVOID)third,0,NULL);
    
        WaitForMultipleObjects(g_Number,hThread,TRUE,INFINITE); 
        CloseHandle( hThread[0] ); 
        CloseHandle( hThread[1] ); 
        CloseHandle( hThread[2] );
    
        CloseHandle( hSemp1 ); 
        CloseHandle( hSemp2 ); 
        CloseHandle( hSemp3 ); 
        return 0; 
    }
    
    DWORD WINAPI ThreadProc1(__in  LPVOID lpParameter) 
    { 
        WaitForSingleObject(hSemp1, INFINITE);//等待信号量 
        cout<<(int)lpParameter<<endl; 
        ReleaseSemaphore(hSemp1,1,NULL);//释放信号量 
        return 0; 
    }
    
    DWORD WINAPI ThreadProc2(__in  LPVOID lpParameter) 
    { 
        WaitForSingleObject(hSemp2, INFINITE);//等待信号量 
        cout<<(int )lpParameter<<endl; 
        ReleaseSemaphore(hSemp2,1,NULL);//释放信号量 
        return 0; 
    }
    
    DWORD WINAPI ThreadProc3(__in  LPVOID lpParameter) 
    { 
        WaitForSingleObject( hSemp3, INFINITE);//等待信号量 
        cout<<(int)lpParameter<<endl; 
        ReleaseSemaphore(hSemp3,1,NULL);//释放信号量 
        return 0; 
    }
  • 相关阅读:
    idea设置tomcat虚拟路径的两种方法
    改变javahome但是java version并没有修改的解决方案
    1. 两数之和
    88. 合并两个有序数组
    53. 最大子数组和(欠分治法)
    【记录】orcle安装
    191. 位1的个数
    【记录】plsql安装
    IP2region离线解析IP地址
    flink 常用命令
  • 原文地址:https://www.cnblogs.com/cyblogs/p/9948379.html
Copyright © 2020-2023  润新知