• 多线程编程示例2(结合实例)


    5.互斥量(Mutex)

    #pragma once
    
    #define _CRTDBG_MAP_ALLOC
    #include<cstdio>
    #include<Windows.h>
    #include<crtdbg.h>
    #include<process.h>
    
    unsigned int count = 0;
    const unsigned int threadnum = 50;
    HANDLE Mutex;
    CRITICAL_SECTION ThreadPar;
    
    unsigned int _stdcall ThreadFun(LPVOID pM)
    {
        UINT num = *(UINT*)pM;
        ReleaseMutex(Mutex); //触发互斥量
    
        Sleep(50); //做点什么
    
        EnterCriticalSection(&ThreadPar);
        ++count;
        printf("线程编号为%3d,全局资源值为%3d
    ", num, count);
        LeaveCriticalSection(&ThreadPar);
    
        return 0;
    }
    
    int main()
    {
        Mutex = CreateMutex(NULL, FALSE, NULL);
        InitializeCriticalSection(&ThreadPar);
    
        UINT i = 0;
        HANDLE handle[threadnum];
    
        for (i = 0; i < threadnum; i++)
        {
            //进入子线程ID号关键区域
            handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, &i, 0, NULL);
            WaitForSingleObject(Mutex, INFINITE); //等待互斥量被触发
        }
        WaitForMultipleObjects(threadnum, handle, TRUE, INFINITE);
    
        CloseHandle(Mutex);
        DeleteCriticalSection(&ThreadPar);
        for ( i = 0; i < threadnum; i++)
        {
            CloseHandle(handle[i]);
        }
    
        //检测内存泄漏
        _CrtDumpMemoryLeaks();
        return 0;
    }

    运行结果:

    依然无法做到同步,具体原因与临界区域类似,存在一个线程所有权。

    关于互斥量的有趣地方就是它可以使用在进程之间的多线程控制,其中有一个遗弃处理。

    具体可以参考:http://blog.csdn.net/morewindows/article/details/7470936,很不错的解释

    6.信号量(Semaphore)

    #pragma once
    
    #define _CRTDBG_MAP_ALLOC
    #include<cstdio>
    #include<Windows.h>
    #include<crtdbg.h>
    #include<process.h>
    
    unsigned int count = 0;
    const int threadnum = 20;
    HANDLE ThreadSemaphore;
    CRITICAL_SECTION ThreadPar;
    
    unsigned int _stdcall ThreadFun(LPVOID pM)
    {
        UINT num = *(UINT*)pM;
        /*ReleaseSemaphore函数参数
          1:信号量的句柄
          2:增加个数,必须大于0且不大于最大资源数
          3:先前的资源计数,设为NULL表示不传递
        */
        ReleaseSemaphore(ThreadSemaphore,1,NULL); //信号量++
    
        Sleep(50); //做点什么
    
        EnterCriticalSection(&ThreadPar);
        ++count;
        printf("线程编号为%3d,全局资源值为%3d
    ", num, count);
        LeaveCriticalSection(&ThreadPar);
    
        return 0;
    }
    
    int main()
    {
        //初始化信号量和关键段
        /*CreateSemaphore函数说明
          1:安全控制
          2:初始资源数量
          3:最大并发数量
          4:信号量的名称
        */
        ThreadSemaphore = CreateSemaphore(NULL, 0, 1, NULL); //当前0个资源,最多允许一个同时访问
        InitializeCriticalSection(&ThreadPar);
    
        int i = 0;
        HANDLE handle[threadnum];
        for ( i = 0; i < threadnum; i++)
        {
            handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, &i, 0, NULL);
            WaitForSingleObject(ThreadSemaphore, INFINITE); //等待信号量>0
        }
        WaitForMultipleObjects(threadnum, handle, TRUE, INFINITE);
    
        //销毁信号量和关键段
        CloseHandle(ThreadSemaphore);
        DeleteCriticalSection(&ThreadPar);
        for (i = 0; i < threadnum; i++)
        {
            CloseHandle(handle[i]);
        }
    
        //检测内存泄漏
        _CrtDumpMemoryLeaks();
        return 0;
    }

    运行结果:

    信号量同Event,能够解决线程同步问题。

    由于信号量可以计算资源当前剩余量并根据当前剩余量与零比较来决定信号量是处于触发状态或是未触发状态,因此信号量的应用范围相当广泛。

    信号量辅助理解解释:

    以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
    在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
    抽象的来讲,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程/进程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。当一个线程调用Wait操作时,它要么得到资源然后将信号量减一,要么一直等下去(指放入阻塞队列),直到信号量大于等于一时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为释放了由信号量守护的资源。

    关于关键段 事件 互斥量 信号量的总结:

    参考;http://blog.csdn.net/morewindows/article/details/7538247

    很经典的解释,多线程编程1、2为参考其内容进行的实验。

  • 相关阅读:
    Python 规范
    Hql
    Python
    IIS 日志分析
    NHibernate 知识点整理
    微软开放了.NET 4.5.1的源代码
    自定义消息编码绑定实现
    使用自定义绑定
    WCF安全:通过 扩展实现用户名密码认证
    WCF 几种错误
  • 原文地址:https://www.cnblogs.com/jason1990/p/4717599.html
Copyright © 2020-2023  润新知