信号量

  • 互斥量:某段时间只能让一个线程运行,其他休眠。
  • 信号量:多个线程运行,其他线程休眠
  • 临界区:只能让一个线程运行,其他休眠。
  • 原子操作:操作速度最快,因为他不需要等待和切换线程。
  • 事件也可以实现线程互斥。

1.信号量
 主要解决线程通信,实现同一时刻多个线程同时访问一个资源,当同一时刻只有一个线程在访问时它就和互斥量是一样的,所以有时说信号量是Mutex的退化版。它也是系统内核对象. 系统提供相关的API有:

CreateSemaphore

OpenSemaphore

ReleaseSemaphore

WaitForSingleObject/WaitForMultipleObjects

CloseHandle

2.理解

  • Semaphore分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。
    以 一个停车场是运作为例。为了简单起见,假设停车场只有三个车位,一开始 三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处 等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。
    在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
  • Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。一般的用法是用于串行化对critical section代码的访问,保证这段代码不会被并行的运行。


    Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。一般的用法是,用于限制对于某一资源的同时访问。

3.函数的参数



CloaseHandle(thread);thread线程执行完毕,然后退出。
当信号量设置是1,也可以实现互斥。
信号量遇到0就死等,遇到其他数,减1.

2.例子

例一:

//关卡的作用

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define  id  "haihua"
#define  MAX 5

//0无限等待

DWORD WINAPI myworker(void *p)
{
    int *pint = p;
    printf("
myworker%d is running", *pint);

    HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, id);//打开一个信号
    if (myhsem) //myheasm!=null
    {
        printf("
myworker%d is waitting", *pint);

        //初始化信号为0,为0就会死锁,0,信号量不减去
        //WaitForSingleObject不为 0的情况下,信号量-1
        if (WaitForSingleObject(myhsem,INFINITE)==WAIT_OBJECT_0)//等到了信号
        {
            printf("
myworker%d is gettting", *pint);
            Sleep(3000);
            printf("
myworker%d is leaving,", *pint);

            ///ReleaseSemaphore(myhsem, 1, NULL);//释放资源 ,+1

            CloseHandle(myhsem);//执行完成退出

        }
    
    }

    return 1;
}


int main()
{
    //创建信号对象,
    HANDLE  hSEM = CreateSemaphore(NULL, 0, MAX, id);//开辟一个信号,最大计数是5.0

    int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    HANDLE hd[10] = { 0 };
    for (int i = 0; i < 10;i++)
    {
        hd[i] = CreateThread(NULL, 0, myworker, a + i, 0, NULL);//创建是个线程
    }
    Sleep(5000);

    printf("激活线程");
    ReleaseSemaphore(hSEM, MAX, NULL); //最多一次放过5

    WaitForMultipleObjects(10, hd, TRUE, INFINITE);

    CloseHandle(hSEM);

    system("pause");
}

例二:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int  num = 0;

DWORD WINAPI add(void*p)
{
    HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, "xiaobin");//打开一个信号
    if (myhsem) //myheasm!=null
    {

        if (WaitForSingleObject(myhsem, INFINITE) == WAIT_OBJECT_0)//等到了信号
        {
            for (int i = 0; i < 100000; i++)
            {
                num++;
            }
            ReleaseSemaphore(myhsem, 1, NULL);

            CloseHandle(myhsem);//执行完成退出

        }
    
    }
    else
    {
        printf("信号量获取失败
");
    }

}

int main()
{

    //创建信号对象,
    HANDLE  hSEM = CreateSemaphore(NULL, 0, 1, "xiaobin");//开辟一个信号,最大计数是5.0


    HANDLE hd[64] = { 0 };
    for (int i = 0; i < 64; i++)
    {
        hd[i] = CreateThread(NULL, 0, add,NULL, 0, NULL);//创建是个线程
    }
    Sleep(2000);
    printf("激活线程");
    ReleaseSemaphore(hSEM, 1, NULL); 


    WaitForMultipleObjects(64, hd, TRUE, INFINITE);
    printf("%d", num);

    CloseHandle(hSEM);
    system("pause");

}
原文地址:https://www.cnblogs.com/sjxbg/p/5789781.html