阅读本篇之前推荐阅读以下姊妹篇:

《秒杀多线程第四篇一个经典的多线程同步问题》

《秒杀多线程第五篇经典线程同步关键段CS》

《秒杀多线程第六篇经典线程同步事件Event》

《秒杀多线程第七篇经典线程同步互斥量Mutex》

前面介绍了关键段CS、事件Event、互斥量Mutex在经典线程同步问题中的使用。本篇介绍用信号量Semaphore来解决这个问题。

首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便。下面是这几个函数的原型和使用说明。

第一个 CreateSemaphore

函数功能:创建信号量

函数原型:

HANDLE CreateSemaphore(

LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,

LONG lInitialCount,

LONG lMaximumCount,

LPCTSTR lpName

);

函数说明:

第一个参数表示安全控制,一般直接传入NULL。

第二个参数表示初始资源数量。

第三个参数表示最大并发数量。

第四个参数表示信号量的名称,传入NULL表示匿名信号量。

第二个 OpenSemaphore

函数功能:打开信号量

函数原型:

HANDLE OpenSemaphore(

DWORD dwDesiredAccess,

BOOL bInheritHandle,

LPCTSTR lpName

);

函数说明:

第一个参数表示访问权限,对一般传入SEMAPHORE_ALL_ACCESS。详细解释可以查看MSDN文档。

第二个参数表示信号量句柄继承性,一般传入TRUE即可。

第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。

第三个 ReleaseSemaphore

函数功能:递增信号量的当前资源计数

函数原型:

BOOL ReleaseSemaphore(

HANDLE hSemaphore,

LONG lReleaseCount,

LPLONG lpPreviousCount

);

函数说明:

第一个参数是信号量的句柄。

第二个参数表示增加个数,必须大于0且不超过最大资源数量。

第三个参数可以用来传出先前的资源计数,设为NULL表示不需要传出。

注意:当前资源数量大于0,表示信号量处于触发,等于0表示资源已经耗尽故信号量处于末触发。在对信号量调用等待函数时,等待函数会检查信号量的当前资源计数,如果大于0(即信号量处于触发状态),减1后返回让调用线程继续执行。一个线程可以多次调用等待函数来减小信号量。

最后一个 信号量的清理与销毁

由于信号量是内核对象,因此使用CloseHandle()就可以完成清理与销毁了。

在经典多线程问题中设置一个信号量和一个关键段。用信号量处理主线程与子线程的同步,用关键段来处理各子线程间的互斥。详见代码:

  1. #include <stdio.h>
  2. #include <process.h>
  3. #include <windows.h>
  4. long g_nNum;
  5. unsigned int __stdcall Fun(void *pPM);
  6. const int THREAD_NUM = 10;
  7. //信号量与关键段
  8. HANDLE            g_hThreadParameter;
  9. CRITICAL_SECTION  g_csThreadCode;
  10. int main()
  11. {
  12. printf("     经典线程同步 信号量Semaphore\n");
  13. printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
  14. //初始化信号量和关键段
  15. g_hThreadParameter = CreateSemaphore(NULL, 0, 1, NULL);//当前0个资源,最大允许1个同时访问
  16. InitializeCriticalSection(&g_csThreadCode);
  17. HANDLE  handle[THREAD_NUM];
  18. g_nNum = 0;
  19. int i = 0;
  20. while (i < THREAD_NUM)
  21. {
  22. handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
  23. WaitForSingleObject(g_hThreadParameter, INFINITE);//等待信号量>0
  24. ++i;
  25. }
  26. WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
  27. //销毁信号量和关键段
  28. DeleteCriticalSection(&g_csThreadCode);
  29. CloseHandle(g_hThreadParameter);
  30. for (i = 0; i < THREAD_NUM; i++)
  31. CloseHandle(handle[i]);
  32. return 0;
  33. }
  34. unsigned int __stdcall Fun(void *pPM)
  35. {
  36. int nThreadNum = *(int *)pPM;
  37. ReleaseSemaphore(g_hThreadParameter, 1, NULL);//信号量++
  38. Sleep(50);//some work should to do
  39. EnterCriticalSection(&g_csThreadCode);
  40. ++g_nNum;
  41. Sleep(0);//some work should to do
  42. printf("线程编号为%d  全局资源值为%d\n", nThreadNum, g_nNum);
  43. LeaveCriticalSection(&g_csThreadCode);
  44. return 0;
  45. }

运行结果如下图:

可以看出来,信号量也可以解决线程之间的同步问题。

由于信号量可以计算资源当前剩余量并根据当前剩余量与零比较来决定信号量是处于触发状态或是未触发状态,因此信号量的应用范围相当广泛。本系列的《秒杀多线程第十篇 生产者消费者问题》将再次使用它来解决线程同步问题,欢迎大家参阅。

至此,经典线程同步问题全部结束了,下一篇《秒杀多线程第九篇经典多线程同步问题总结》将会对其作个总结以梳理各知识点。

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/7481609

如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

转---秒杀多线程第八篇 经典线程同步 信号量Semaphore的更多相关文章

  1. 秒杀多线程第八篇 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <且不超过最大资源数量. 第三个參数能够用来传出先前的资源计数,设为NULL表示不须要传出. 注意:当 ...

  2. 秒杀多线程第八篇 经典线程同步 信号量Semaphore (续)

    java semaphore实现: Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,在进程控制方面都有应用.Java 并发库 的Semaphore 可以很轻松完成信号 ...

  3. 秒杀多线程第六篇 经典线程同步 事件Event

    原文地址:http://blog.csdn.net/morewindows/article/details/7445233 上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的“线程所有权” ...

  4. 转--- 秒杀多线程第六篇 经典线程同步 事件Event

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...

  5. 转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  6. 转---秒杀多线程第五篇 经典线程同步 关键段CS

    上一篇<秒杀多线程第四篇 一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题. 本文首先介绍下如何使用关键段,然 ...

  7. 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    本文转载于:http://blog.csdn.net/morewindows/article/details/7470936 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用 ...

  8. 秒杀多线程第五篇 经典线程同步 关键段CS

    本文首先介绍下如何使用关键段,然后再深层次的分析下关键段的实现机制与原理. 关键段CRITICAL_SECTION一共就四个函数,使用很是方便.下面是这四个函数的原型和使用说明. 函数功能:初始化 函 ...

  9. 秒杀多线程第七篇 经典线程同步 互斥量Mutex(续)

    java使用Synchronized关键字实现互斥,而同时有Lock支持. 这两个的效果是等同的,Synchronized性能的起伏较大,而lock比较收敛. 为了代码的可读性,Synchronize ...

随机推荐

  1. 20155328 2016-2017-2 《Java程序设计》 第一周学习总结

    20155328 2016-2017-2 <Java程序设计> 第一周学习总结 教材学习内容总结 本周学习目标是浏览<Java学习笔记>中的十八章,其中第一章和第二章认真学习, ...

  2. 20155332 2016-2017-2《Java程序设计》课程总结

    20155332 2016-2017-2<Java程序设计>课程总结 1.每周作业链接汇总 2.博客之最 3.实验链接汇总 博客链接汇总 预备作业1:那些年陪伴我的老师+我期待的师生关系 ...

  3. zabbix最新版3.4搭建(根据官方文档适当修改)

    操作系统:CentOS Linux release 7.4.1708 (Core) 1.安装apache 1.1 安装apache yum install httpd httpd-devel 1.2 ...

  4. (三)SpringBoot2.0基础篇- 持久层,jdbcTemplate和JpaRespository

    一.介绍 SpringBoot框架为使用SQL数据库提供了广泛的支持,从使用JdbcTemplate的直接JDBC访问到完整的“对象关系映射”技术(如Hibernate).Spring-data-jp ...

  5. cogs1439 货车运输

    cogs1439 货车运输 一道傻逼板子题. 边一定在最大生成树上,这个可以用消圈证明 然后kruskal跑一遍再搜一遍再建ST表再跑LCA这题就做完了. RT PS.交上去的代码把Kruskal打成 ...

  6. new与alloc/init的区别

    alloc:分配内存. init:初始化. new:代替上面两个函数:分配内存,并且初始化. 注意: 1.在实际开发中很少会用到new,一般创建对象时我们一般是 [[className alloc]i ...

  7. 探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式

    如果你的网站需要被世界各地的人访问,访问者会使用各种不同的语言和文字书写习惯,那么创建一个支持多语言的网站就是十分必要的了,这一篇文章就讲述怎么快速合理的创建网站对多语言的支持.接下来通过一个实例来讲 ...

  8. Zigbee系列(网络)

    Zigbee设备类型 Coordinator:形成网络,选择信道.PANID.允许其他设备加入等. Router: 作为路由节点,转发报文. End Device: 终端节点,不转发报文. Zigbe ...

  9. 自动化运维工具saltstack03 -- 之SaltStack的数据系统

    SaltStack数据系统 saltstack有两种数据系统:grains与pillar 1.SaltStack数据系统之grains grains可以收集minion端的静态数据(即机器启动时收集一 ...

  10. 423. Valid Parentheses【LintCode java】

    Description Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine ...