zoukankan      html  css  js  c++  java
  • 信号量

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

    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");
    
    }
  • 相关阅读:
    Spring+Spring MVC+Hibernate框架搭建实例
    数据结构:串
    为什么java中用枚举实现单例模式会更好
    验证码原理分析及实现
    Servlet监听器——实现在线登录人数统计小例子
    IntelliJ IDEA 远程调试 Tomcat 的方法
    SQL注入的一些技巧分享
    Java中String与byte[]的转换
    JavaSE基础:集合类
    二叉树的非递归遍历
  • 原文地址:https://www.cnblogs.com/sjxbg/p/5789781.html
Copyright © 2011-2022 走看看