【.NET深呼吸】线程信号量(Semaphore)

Semaphore类可以控制某个资源允许访问的线程数,Semaphore有命名式的,也有不命名的;如果不考虑跨进程工作,一般在代码中使用不命名方式即可。

信号量有点类似于等待句柄,某个线程如果调用了WaitOne方法,这个线程就会暂停,并且等待有可用的信号量时才会继续执行;某个线程调用Release方法,就会释放一个信号计数值,每调用一次就释放一个,如果想一次性释放N个信号,可以调用Release(int)重载,把要释放的数量传递给方法参数,但这个数值不能超过Semaphore实例化时所指定的最大值,否则会引发异常。

Semaphore构造函数可以指定允许的最大信号量,以及默认的信号量。声明如下:

Semaphore(int initialCount, int maximumCount);

maximumCount参数指定该对象允许的最大信号量;initialCount参数指定默认值,这个默认值不能超过maximumCount指定的最大值。即该Semaphore实例默认允许多少个线程收到信号(访问资源)。

当某个占用资源的线程调用Release方法后,它会释放出一个或多个信号,这时候,其他等待的线程就可以继续执行。

只要是涉及到线程问题都特别难说清楚,相当抽象,相当考验人的理解能力。

比如,图书馆里面有五本《X瓶梅》,但想借这本书的有20人。前面五个人自然很轻松就借到(进入访问圈,这五个线程以外的线程等待),其他人只好等了。

过了几天后,有个家伙通宵看书,终于看完了,因此他还了书,这时候,剩下的15个人看谁的动作快,可以借到刚还回去的这本书。

再过了几天,又有两个人看完了,还书。此时,剩下的14个人中,有两个人可以借得此书。

大概的原理就是这样,下面看看例子。

    class Program
    {
        // 生成随机数,以延迟每个任务的执行时间
        static Random rand = new Random();
        // 声明Semaphore变量,以控制线程信号量
        static Semaphore sm = null;
        static void Main(string[] args)
        {
            sm = new Semaphore(1, 4); //实例化
            // 启动10个任务
            for (int i = 0; i < 10; i++)
            {
                Task t = new Task(DoWork, "任务" + (i + 1));
                t.Start();
            }

            // 防止DOS窗口立即退出
            Console.Read();
        }

        private static async void DoWork(object p)
        {
            sm.WaitOne(); //等待花开
            string tn = p?.ToString();
            Console.WriteLine($"{tn} 已获得访问。");
            await Task.Delay(rand.Next(1, 10) * 1000);
            // 释放
            sm.Release(); //花谢了
            Console.WriteLine($"{tn}已释放。");
        }
    }

多线程开发我最喜欢用Task类,方便简单强大好用高大上,而且它还能自行处理CPU多个核的问题。在上面例子中,有10个任务要执行,但我所实例化的Semaphore对象给的最大访问线程数为4,而默认状态下只允许1个线程同时访问。

所以,10个任务启动后,其中一个会抢到访问权,其他任务就等吧。这时候Semaphore对象可访问数为0。因为默认只允许1,现在有一个线程抢了,所以剩下就是0个访问权了。

当这个抢到访问权的任务调用Release方法后,访问权被释放,这时候剩下的9个任务就开始抢,谁抢到谁就执行……依此类推。

看看运行结果。

任务1手快,它先抢到了访问权,于是它dododo,do完后,调用Release方法释放,然后任务3人品好,就抢到了访问权,然后XXXXX,X完后调用Release释放。其他线程继续抢……

估计看完以上例子后,大家应该有点头绪了。

现在,我们把上面的代码改一下,在初始化Semaphore对象时的默认值从1改为3。

sm = new Semaphore(3, 4);

默认允许3个线程同时访问资源,最大数量为4。

然后再次运行,结果如下:

因为默认允许3个线程同时进入,所以在输出结果中,前面三个任务都能获取访问权,而其他的任务只能等待机会。当前面已获得资源的三个任务中有一个或者N个进行释放后,剩下的任务又开始抢机会。

本文示例下载地址:http://files.cnblogs.com/files/tcjiaan/DemoApp.zip

时间: 2024-10-13 17:50:59

【.NET深呼吸】线程信号量(Semaphore)的相关文章

python线程信号量semaphore(33)

通过前面对 线程互斥锁lock /  线程事件event / 线程条件变量condition / 线程定时器timer 的讲解,相信你对线程threading模块已经有了一定的了解,同时执行多个线程的确可以提高程序的效率,但是并非线程的数量越多越好,可能对于计算机而言,你直接运行20~30线程可能没太大影响,如果同时运行上千个甚至上万个呢?我相信你电脑会直接瘫痪…… 一.semaphore信号量原理 多线程同时运行,能提高程序的运行效率,但是并非线程越多越好,而semaphore信号量可以通过内

java 信号量Semaphore

在很多情况下,可能有多个线程需要访问数目很少的资源.假想在服务器上运行着若干个回答客户端请求的线程.这些线程需要连接到同一数据库,但任一时刻 只能获得一定数目的数据库连接.你要怎样才能够有效地将这些固定数目的数据库连接分配给大量的线程? 答:1.给方法加同步锁,保证同一时刻只能有一个人去调用此方法,其他所有线程排队等待,但是此种情况下即使你的数据库链接有10个,也始终只有一个处于使 用状态.这样将会大大的浪费系统资源,而且系统的运行效率非常的低下. 2.另外一种方法当然是使用信号量,通过信号量许

java笔记--对信号量Semaphore的理解与运用

java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或逻辑的)线程数目. 一个信号量有且仅有3种操作,且它们全部是原子的:初始化.增加和减少 增加可以为一个进程解除阻塞: 减少可以让一个进程进入阻塞. --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3910406.html "谢谢-- 信

四.并发编程 (线程信号量)

一 .线程信号量(Semaphore) 号量semaphore 可以控制同时运行执行的线程数量. 信号量semaphore内部维护了一个条件变量和一个计数器. import threading,time sem=threading.Semaphore(3) # 控制线程的数量 意思三个三个线程走 def run(): with sem: for i in range(10): print(threading.current_thread().name,i) time.sleep(2) if __

经典线程同步 信号量Semaphore

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

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

版权声明:本文为博主原创文章,未经博主允许不得转载. 阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore

linux系统编程:线程同步-信号量(semaphore)

线程同步-信号量(semaphore) 生产者与消费者问题再思考 在实际生活中,只要有商品,消费者就可以消费,这没问题.但生产者的生产并不是无限的,例如,仓库是有限的,原材料是有限的,生产指标受消费指标限制等等.为了进一步,解决好生产者与消费者问题,引入信号量进机制. 信号量 信号量(semaphore)是互斥量的升级版:互斥量的状态为0或1,而信号量可以为n.也就是说,使用互斥量时,最多允许一个线程进入关键区,而信号量允许多个,具体值是信号量当前的内部值. 相关函数 sem_t //信号量类型

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

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

12、第七周-网络编程 - 线程中的信号量(Semaphore)

互斥锁同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据.简单介绍如下: 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作.而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源.比如对全局变量的访问,有时要加锁,操作完了,在解锁.有的时候锁和信号量会同时使用的. 也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比