.Net 下信号量(Semaphore)的一种实现

动机

    从开始接触多线(进)程编程模型开始,学习的就是和信号量(Semaphore)相关的同步原语。不知道为什么 .Net Framework 里却没有相应的东东。要命的是, 我以前有很多久经考验的C++代码都是用她来实现的, 为了不使革命先烈的药白吃, 血白流, 只好自己生一个了。

什么是信号量(Semaphore)

    如果你已经了解信号量(Semaphore)的概念了,请跳过这一段。
   
    信号量(Semaphore)是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

    我们来看看一个停车场是怎样运作的。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这是如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。

    在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

    更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait等待)操作时,它要么通过然后将信号量减一,要么一自等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是应为加操作实际上是释放了由信号量守护的资源。

实现

   大家都知道,.Net Framework类库中提供的线程同步设施包括:

    Monitor, AutoResetEvent, ManualResetEvent,Mutex,ReadWriteLock和 InterLock。 其中 AutoResetEvent, ManualResetEvent,Mutex派生自WaitHandler,它们实际上是封装了操作系统提供的内核对象。而其它的应当是在.Net虚拟机中土生土长的。显然来自操作系统内核对象的设施使用起来效率要差一些。不过效率并不是我们这里要考虑的问题,我们将使用两个 Monitor 和 一个ManualResetEvent 对象来模拟一个信号量。

代码如下:

    public class Semaphore
    {
        private ManualResetEvent waitEvent = new ManualResetEvent(false);
        private object syncObjWait = new object();
        private int     maxCount = 1;      file://最大资源数
        private int     currentCount = 0;  file://当前资源数

        public Semaphore()
        {

        }

        public Semaphore( int maxCount )
        {
            this.maxCount = maxCount;
        }

        public bool Wait()
        {
            lock( syncObjWait )      file://只能一个线程进入下面代码
            {
                bool waitResult = this.waitEvent.WaitOne();   file://在此等待资源数大于零
                if( waitResult )
                {
                    lock( this )
                    {
                        if( currentCount > 0 )
                        {
                            currentCount--;
                            if( currentCount == 0 )
                            {
                                this.waitEvent.Reset();
                            }

                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert( false, "Semaphore is not allow current count < 0" );
                        }
                    }
                }
                return waitResult;
            }
        }

        /**//// <summary>
        /// 允许超时返回的 Wait 操作
        /// </summary>
        /// <param name="millisecondsTimeout"></param>
        /// <returns></returns>
        public bool Wait( int millisecondsTimeout )
        {
            lock( syncObjWait )  // Monitor 确保该范围类代码在临界区内
            {
                bool waitResult = this.waitEvent.WaitOne(millisecondsTimeout,false);
                if( waitResult )
                {
                    lock( this )
                    {
                        if( currentCount > 0 )
                        {
                            currentCount--;
                            if( currentCount == 0 )
                            {
                                this.waitEvent.Reset();
                            }

                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert( false, "Semaphore is not allow current count < 0" );
                        }
                    }
                }
                return waitResult;
            }
        }

        public bool Release()
        {
            lock( this ) // Monitor 确保该范围类代码在临界区内
            {
                currentCount++;
                if( currentCount > this.maxCount )
                {
                    currentCount = this.maxCount;
                    return false;
                }
                this.waitEvent.Set();  file://允许调用Wait的线程进入
            }
            return true;
        }

    }

时间: 2024-08-20 00:48:18

.Net 下信号量(Semaphore)的一种实现的相关文章

JAVA多线程--信号量(Semaphore)

简介         信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确.合理的使用公共资源.         一个计数信号量.从概念上讲,信号量维护了一个许可集.如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可.每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者.但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动.拿到信号量的线程可以进

线下推广网站的7种方法

推广 线下推广网站的7种方法 1.总是将网址放在信头.名片和电子邮件的签名文件上.这样潜在的浏览者就有可能看到它. 2.如果你的雇员穿的是制服,将网址印上去,从而是你的客户看到你网址的流动广告. 3.将网址印在你送出去的杯子.T恤.钥匙链等促销品上,它是每天提醒人们参观你网站的好方法. 4.确保在你发给新闻写作人员的新闻通讯中都包含你的网址.由于非常方便,他们也许将你公司写入他们的文章中. 5.不要忘记将你的网址放在你的黄页广告中,这是人们每天都看的地方. 6.你的公司有车辆吗?确保你的网址印在

Excel中制作下拉菜单的4种方法

Excel中制作下拉菜单的4种方法   其实还有另外3种: 1.创建列表 在一列中按alt+向下箭头,即可生成一个下拉菜单(创建列表).此方法非常简单. 2.开发工具 - 插入 - 组合框(窗体控件) 如果你的excel没有[开发工具]选项,可以从 文件 - 选项 - 自定义功能区,选中"开发工具".(excel2007为office按钮 - excel选项 - 常规 - 显示"开发工具") 3.开发工具 - 组合框(ActiveX控件) 注: 在"设计模

win8下磁盘分区的三种操作方式

  很多用户对电脑系统的认识大部分都停留在表面,关于电脑的知识也是非常缺乏,再加上新推出的win8系统的界面操作和之前的系统有很大的不同,所以用户就有些茫然失措,因此这里就来跟大家普及一下win8系统下磁盘分区的几种操作方式. 一.创建磁盘分区 1.将鼠标光标移动到屏幕右下,在弹出的菜单上点击"设置". 2.在弹出的菜单上点击"控制面板",打开"控制面板". 3.打开控制面板,点击"系统和安全". 4.点击"创建并格

归纳下js面向对象的几种常见写法总结_javascript技巧

//定义Circle类,拥有成员变量r,常量PI和计算面积的成员函数area()  1.工厂方式 var Circle = function() { var obj = new Object(); obj.PI = 3.14159; obj.area = function( r ) { return this.PI * r * r; } return obj; } var c = new Circle(); alert( c.area( 1.0 ) ); 2.比较正规的写法 function C

JS 实现导航菜单中的二级下拉菜单的几种方式_javascript技巧

最近整理了, JS 实现导航菜单中的二级下拉菜单的三种方式,便于项目中应用.  如何实现导航菜单栏中的二级下拉菜单? 我们在淘宝.搜狐等大型网站上都可以看到使用的一些二级下拉菜单,比如下面这张图片. 但是如何实现类似的图片呢?实际上,我们有至少三种方式来实现,下面,我附上代码供大家参考. 1.仅使用html和css <meta charset="UTF-8"> <title>Document</title> <style> *{margi

ubuntu下安装程序的三种方法总结(推荐)_Linux

引言 在ubuntu当中,安装应用程序我所知道的有三种方法,分别是apt-get,dpkg安装deb和make install安装源码包三种.下面针对每一种方法各举例来说明. apt-get方法 使用apt-get install来安装应用程序算是最常见的一种安装方法了,比如我要安装build-essential这个软件,使用以下,他会帮我把所有的依赖包都一起安装了. sudo apt-get install build-essential 执行上述命令以后,我们可以看到一下信息,The fol

云计算环境下基于Mashup的一种电信网络能力服务提供模式

云计算环境下基于Mashup的一种电信网络能力服务提供模式 刘勇 乔秀全 李晓峰 在电信运营商逐步开放其电信能力API的背景下,基于Mashup的业务构建模式,提出了一种云计算环境下的电信网络能力服务提供模式.该模式将Mashup的理念移植到电信能力上,并将电信能力封装成Web Element的形式呈现给用户,进一步提升了电信网络能力服务的抽象层次. 关键词:云计算环境 Telecom 2.0 Mashup 服务提供模式 Web Element [下载地址]:http://bbs.chinacl

Java 信号量 Semaphore使用方法详解

在用Semaphore 信号量的时候,感觉对公平调度比较有用,可以控制多线程争夺资源时候,最大可以几个在执行,随手写了代码测试下,如下: 说明: 1. acquire() 获取一个许可,如果没有就等待 2. release() 释放一个许可 3. Semaphore可以控制某个资源可被同时访问的个数,自行初始化的数量,为1当然就顺序执行了 package com.i5a6.semp.test;   import java.util.Random; import java.util.concurr