zoukankan      html  css  js  c++  java
  • Chapter09“内核模式下的线程同步”之信号量内核对象

    信号量规则如下:

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

    2.       如果当前资源计数等于0,信号量处于非触发状态。

    3.       系统不允许当前资源计数为负数。

    4.       当前资源计数不会比资源最大值还大。

     

           一个线程通过调用一个等待函数(传递信号量对应的句柄作为参数)获取访问资源的权限。等待函数内部会检测信号量当前的资源计数,如果资源计数值等于0,则线程阻塞,处于等待状态;如果资源计数值大于0(即信号量处于触发状态),则计数减一之后当前调用的线程处于可调度状态。

           有趣的是,信号量执行测试-设置(test-set)原子式(atomically)的操作。当你用一个信号量去请求资源时,操作系统检测资源是否可用和将可用资源数减一操作时中间不会被其他线程中断的,只有在资源计数减一之后,系统才允许其他线程去请求访问资源。

     

     

    下面再介绍信号量(Semaphore)相关的函数:

    1)       信号量创建函数——CreateSemaphore函数
    HANDLE CreateSemaphore(
                                              __in_optPSECURITY_ATTRIBUTE psa,

                                              __in LONG lInitialCount,
                                              __inLONG lMaximumCount,
                                              __in_optPCTSTR pszName)

    具体的函数说明请查看上面的MSDN链接。

    信号量创建函数——CreateSemaphoreEX函数,可以指定想要的访问权限。

    HANDLE CreateSemaphoreEx(

                                                     __in_opt PSECURITY_ATTRIBUTESpsa,
                                                     __inLONG lInitialCount,
                                                     __inLONG lMaximumCount,
                                                     __in_optPCTSTR pszName,
                                                     __reservedDWORD dwFlags,
                                                     __inDWORD dwDesiredAccess);

    第一个参数psa指定了一些安全属性。
    第二个参数lInitialCount指定了初始时可用的资源数。
    第三个参数lMaximumCount指定了信号量(Semaphore)能够应用程序能够处理的最大资源数。

     

    2)       打开信号量函数——OpenSemaphore函数
    HANDLE OpenSemaphore(
                                              __in DWORD dwDesiredAccess,
                                              __inBOOL bInheritHandle,
                                              __inPCTSTR pszName);

    3)       增加信号量的当前计数函数——ReleaseSemphore函数
    BOOL ReleaseSemaphore(
                                              __in HANDLE hSemaphore,
                                              __inLONG lReleaseCount,
                                              __out_optPLONG plPreviousCount)

    第一个参数hSemaphore是对应的信号量对象的句柄;
    第二个参数lReleaseCount是要去增加的信号量计数个数;
    第三个参数plPreviousCount,但函数成功后,该参数标记的是之前信号量的计数值。


    一个示例:(代码转自此处

    // 信号量对象句柄
    HANDLE hSemaphore;
    UINT ThreadProc15(LPVOID pParam)
    {
     // 试图进入信号量关口
     WaitForSingleObject(hSemaphore, INFINITE);
     // 线程任务处理
     AfxMessageBox(" 线程一正在执行!");
     // 释放信号量计数
     ReleaseSemaphore(hSemaphore, 1, NULL);
     return 0;
    }
    UINT ThreadProc16(LPVOID pParam)
    {
     // 试图进入信号量关口
     WaitForSingleObject(hSemaphore, INFINITE);
     // 线程任务处理
     AfxMessageBox(" 线程二正在执行!");
     // 释放信号量计数
     ReleaseSemaphore(hSemaphore, 1, NULL);
     return 0;
    }
    UINT ThreadProc17(LPVOID pParam)
    {
     // 试图进入信号量关口
     WaitForSingleObject(hSemaphore, INFINITE);
     // 线程任务处理
     AfxMessageBox(" 线程三正在执行!");
     // 释放信号量计数
     ReleaseSemaphore(hSemaphore, 1, NULL);
     return 0;
    }
    ……
    void OnSemaphore()
    {
     // 创建信号量对象
     hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);
     // 开启线程
     AfxBeginThread(ThreadProc15, NULL);
     AfxBeginThread(ThreadProc16, NULL);
     AfxBeginThread(ThreadProc17, NULL);
    }
    略作分析:

    step1:在OnSemaphore函数体内调用CreateSemaphore函数创建一个初始化值和最大值都为2的信号量(Semaphore),再分别开启三个使用信号量的线程

    step2:每个线程内的代码结构相似,即先调用WaitforSingleObject函数等待信号量去获取对应的资源的访问权限,如果有可用资源,函数返回后,程序继续运行;如果没有可用资源,则线程一直阻塞等待。

    step3:在线程访问完资源后,再调用ReleaseSemaphore函数增加信号量释放资源。

  • 相关阅读:
    MongoDB 备份与恢复
    MongoDB 分片
    MongoDB 复制(副本集)
    MongoDB 聚合
    利用SSL For Free工具3分钟获取Let's Encrypt免费SSL证书
    使用免费SSL证书让网站支持HTTPS访问
    免费资源部落 免费SSL证书Let’s Encrypt安装使用教程:Apache和Nginx配置SSL
    Windows上管理远程Linux VPS/服务器文件工具
    SSH远程会话管理工具
    腾讯云linux服务器安装lnmp一键包
  • 原文地址:https://www.cnblogs.com/java20130722/p/3207133.html
Copyright © 2011-2022 走看看