windows多线程(八) 信号量Semaphore

如果你看到了这里,我就认为你已经对掌握了有关关键段 CriticalSection、互斥量Mutex和事件Event有关的内容,所以最基本的东西就不再介绍了。如果没有掌握上面说的内容,可以看这里:

  1. 关键段 CriticalSection
  2. 互斥量Mutex
  3. 事件Event

一、信号量相关函数说明

(一) 创建信号量CreateSemaphore

1.函数原型



HANDLE WINAPI CreateSemaphore(
        _In_opt_ LPSECURITY_ATTRIBUTES  lpSemaphoreAttributes,
        _In_     LONG lInitialCount,
        _In_     LONG lMaximumCount,
        _In_opt_ LPCWSTR lpName
        );

2.参数说明

  • 第一个参数lpSemaphoreAttributes,表示安全属性。如果是NULL,就表示使用默认属性。
  • 第二个参数lInitialCount,信号量的初始数值,必须大于或等于0,并且小于或等于lMaximumCount
  • 第三个参数lMaximumCount,信号量的最大值,即最大并发数。
  • 第四个参数lpName,信号量的名字,是一个字符串,任何线程(或进程)都可以根据这一名称引用到这个信号量,这个值可以是NULL,表示产生一个匿名信号量。

  • 返回值: 如果成功就返回一个handle,否则传回NULL。

(二) 打开信号量OpenSemaphore

1.函数原型



HANDLE WINAPI OpenSemaphore(
        _In_ DWORD dwDesiredAccess,
        _In_ BOOL bInheritHandle,
        _In_ LPCSTR lpName
        );

2.参数说明

  • 第一个参数dwDesiredAccess,表示访问权限,一般传入SEMAPHORE_ALL_ACCESS。
  • 第二个参数bInheritHandle,表示信号量句柄继承性,一般传入True。
  • 第三个参数lpName,需要打开的信号量的名称。

  • 返回值: 如果成功就返回信号量handle,否则传回NULL。

(三) 信号量解除锁定ReleaseSemaphore

这个函数功能是实现信号量计数器增加一个值,该值通常是1,但不会超过创建信号量时指定的lMaximumCount

1.函数原型



BOOL WINAPI ReleaseSemaphore(
        _In_ HANDLE hSemaphore,
        _In_ LONG lReleaseCount,
        _Out_opt_ LPLONG lpPreviousCount
        );

2.参数说明

  • 第一个参数hSemaphore,信号量的句柄。
  • 第二个参数lReleaseCount,表示信号量值增加的个数,必须大于0且不超过最大资源数,一般为1。
  • 第三个参数lpPreviousCount,传出先前信号量的计数值,设置为NULL表示不需要传出。

  • 返回值: 如果成功就返回True,否则传回False。

(四) 关闭信号量

由于信号量是一个内核对象,关闭时直接调用CloseHandle()就可以了。

二、实例

使用信号量同样可以实现线程的同步,实现每个线程按顺序依次给全局资源加一,代码如下:




//  信号量演示

#include<iostream>
#include <windows.h>

using namespace std;

const int THREAD_NUM = 10;
int g_Num = 0;
CRITICAL_SECTION g_csVar; //创建关键段cs
HANDLE g_ThreadSema;  //创建内核对象,用来初始化信号量

DWORD WINAPI  Func(LPVOID);

int main()
{
    InitializeCriticalSection(&g_csVar);
    g_ThreadSema = CreateSemaphore(NULL, 0, 1, NULL); //创建匿名信号量,初始资源为零,最大并发数为1,

    HANDLE handle[THREAD_NUM];
    DWORD ThreadId[THREAD_NUM];
    int i = 0;
    while (i < THREAD_NUM)
    {
        handle[i] = CreateThread(NULL, 0, Func, &i, 0, &ThreadId[i]);
        WaitForSingleObject(g_ThreadSema, INFINITE); //等待信号量资源数>0
        i++;
    }
    WaitForMultipleObjects(THREAD_NUM, handle, true, INFINITE);
    CloseHandle(g_ThreadSema); //销毁信号量
    DeleteCriticalSection(&g_csVar);//销毁关键段cs
    for (i = 0; i < THREAD_NUM; i++)
    {
        CloseHandle(handle[i]);
    }
    return 0;
}


DWORD WINAPI Func(LPVOID p)
{
    int nThreadNum = *(int*)p;
    EnterCriticalSection(&g_csVar);
    cout << "线程编号为: " << nThreadNum << " 全局资源值为:" << ++g_Num << endl;
    LeaveCriticalSection(&g_csVar);
    ReleaseSemaphore(g_ThreadSema, 1, NULL);  //信号量资源数加一
    return 0;
}

运行结果如下所示:

825979-20180603204250890-1926628340.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值