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

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

秒杀多线程第五篇经典线程同步关键段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()就能够完毕清理与销毁了。

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

#include <stdio.h>
#include <process.h>
#include <windows.h>
long g_nNum;
unsigned int __stdcall Fun(void *pPM);
const int THREAD_NUM = 10;
//信号量与关键段
HANDLE g_hThreadParameter;
CRITICAL_SECTION g_csThreadCode;
int main()
{
printf(" 经典线程同步 信号量Semaphore\n");
printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); //初始化信号量和关键段
g_hThreadParameter = CreateSemaphore(NULL, 0, 1, NULL);//当前0个资源,最大同意1个同一时候訪问
InitializeCriticalSection(&g_csThreadCode); HANDLE handle[THREAD_NUM];
g_nNum = 0;
int i = 0;
while (i < THREAD_NUM)
{
handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
WaitForSingleObject(g_hThreadParameter, INFINITE);//等待信号量>0
++i;
}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); //销毁信号量和关键段
DeleteCriticalSection(&g_csThreadCode);
CloseHandle(g_hThreadParameter);
for (i = 0; i < THREAD_NUM; i++)
CloseHandle(handle[i]);
return 0;
}
unsigned int __stdcall Fun(void *pPM)
{
int nThreadNum = *(int *)pPM;
ReleaseSemaphore(g_hThreadParameter, 1, NULL);//信号量++ Sleep(50);//some work should to do EnterCriticalSection(&g_csThreadCode);
++g_nNum;
Sleep(0);//some work should to do
printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum);
LeaveCriticalSection(&g_csThreadCode);
return 0;
}

执行结果例如以下图:

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

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

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

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

假设认为本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

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

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

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

  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. Ubuntu 11.10开启root用户登陆

    以管理员身份运行 #sudo gedit /etc/lightdm/lightdm.conf 将里面改成 "autologin-user=root" 就可以以root用户登录了

  2. 关于List、Set集合以及Map的使用

    package tingjizifu; import java.util.*; public class TongJi { /* * 使用Scanner从控制台读取一个字符串,统计字符串中每个字符出现 ...

  3. MySql中的事务嵌套

    1.Mysql中的事务必须是InnoDB.Berkeley DB引擎,myisam不支持. 2.Mysql是不支持嵌套事务的,开启了一个事务的情况下,再开启一个事务,会隐式的提交上一个事务. 3.My ...

  4. C#中串口与Modem的通信

    C#中串口与Modem的通信 2007-08-20 09:52643人阅读评论(8)收藏举报 最近一段时间,试验了串口的数据传输.在C#中,其实有一个很好的类SerialPort使串口间的通信变得简单 ...

  5. web页面相关的一些常见可用字符介绍

    首先是一张图片,是一张一些字符以及想对应的HTML实体表示的对照图片.如下: 一.引号模样或内心的些字符 请选择该表格要呈现的字体: 字符以及HTML实体 描述以及说明 " " 这 ...

  6. PHPCMS 标签与解析小记_Jason

    Content模块下的标签解析:phpcms\modules\content\classes\content_tag.class.php 推荐位:public function position

  7. ServerInfo.INI解密

    [GlobalInfo]LastServerName=000781ED2D127FBA074D97444DC82F216443034E66BB341A428B14E326A656B9LastServe ...

  8. Python中else语句块(和if、while、for、try搭配使用)

    学过C/C++的都知道,else语句是和if语句搭配使用的, 但是在Python中,else语句更像是作为一个模块,不仅仅可以和if语句搭配,还可以和循环语句,异常处理语句搭配使用.下面逐个进行介绍: ...

  9. 存储过程中拼接sql的示例

    create or replace package body CRF_CMS_DOCTOR_PKG is --根据医院查询医生PROCEDURE P_HOSPITALBYDOCTOR_LIST ( v ...

  10. memcpy造成其他变量值改变

        以前C/C++遇到过很多很多的问题,有时候费了很久很久时间,很大很大的努力才解决.但是都没有记录下来,现在想想以前的遇到的问题,只知道这样的事情发生过,至于是什么问题,一点印象都没有了.所以遇 ...