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(, ); //实例化
// 启动10个任务
for (int i = ; i < ; i++)
{
Task t = new Task(DoWork, "任务" + (i + ));
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(, ) * );
// 释放
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个线程同时进入,所以在输出结果中,前面三个任务都能获取访问权,而其他的任务只能等待机会。当前面已获得资源的三个任务中有一个或者N个进行释放后,剩下的任务又开始抢机会。

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

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

  1. python线程信号量semaphore(33)

    通过前面对 线程互斥锁lock /  线程事件event / 线程条件变量condition / 线程定时器timer 的讲解,相信你对线程threading模块已经有了一定的了解,同时执行多个线程的 ...

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

    java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或 ...

  3. 对信号量Semaphore的理解与运用

    转: java笔记--对信号量Semaphore的理解与运用 java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量, ...

  4. 经典线程同步 信号量Semaphore

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

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

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

  6. 多线程面试题系列(8):经典线程同步 信号量Semaphore

    前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数 ...

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

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

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

    线程同步-信号量(semaphore) 生产者与消费者问题再思考 在实际生活中,仅仅要有商品.消费者就能够消费,这没问题. 但生产者的生产并非无限的.比如,仓库是有限的,原材料是有限的,生产指标受消费 ...

  9. 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁

    一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...

随机推荐

  1. 伪Textatea的构建(div+table),以及相应的滚动条问题与safari上的优化

    在页面中创建一个不可编辑的文本块,并且文本块的篇幅较大,第一反应是创建一个textarea,并将它的disabled="disabled",并设置相应的scroll属性,就可以构建 ...

  2. haahah

    #DB ``` import os basedir = os.path.abspath(os.path.dirname(__file__))   SQLALCHEMY_DATABASE_URI = ' ...

  3. .net之美学习-前奏

    做程序员已经一年多 可是感觉自己的基础不是很好,最近买呢一本.net之美的书,决定开始读着本书,写篇随笔记录一下,后面我会通过读着个书 把里面的知识点记录下,没一个章节付上自己的总结

  4. 移动端Web页面问题(转载)

    1.安卓浏览器看背景图片,有些设备会模糊.   用同等比例的图片在PC机上很清楚,但是手机上很模糊,原因是什么呢? 经过研究,是devicePixelRatio作怪,因为手机分辨率太小,如果按照分辨率 ...

  5. ubuntu下安装了express2.5.8,如何更新它?

    在ubuntu上通过apt-get install node-express,结果发现它的版本是2.5.8. 想安装express4.0+的版本,一直不能正确安装,所以一时兴起,打算先删掉它,再重新安 ...

  6. java的基础知识运算符

    一.运算符. 1.算数运算符:+,-,*,/,% 2.自增自减 :++ ,-- ++在前 先运算在赋值 ++在后 先赋值后运算 -- 减减同上. 3.赋值运算符 : = ,+=,-=,*=,/= 4. ...

  7. 不可变数组NSArray

    //数组里面不允许存放基本数据类型,只能存放“对象” NSArray *array = [NSArray arrayWithObjects:@"周星星",@"尹天仇&qu ...

  8. sublime Text 3 字体

    1,Comic Sans Ms 2,DejaVu Sans Mono 3,microsoft yahei(微软雅黑) 4,Microsoft Yahei UI(微软雅黑增强版) 5,Ubuntu Mo ...

  9. DSY2287*消失之物

    Description ftiasch 有 N 个物品, 体积分别是 W1, W2, ..., WN. 由于她的疏忽, 第 i 个物品丢失了. "要使用剩下的 N - 1 物品装满容积为 x ...

  10. ubuntu 安装与开始学习

    下载地址 http://cn.ubuntu.com/download/ 经验: 1.遇到安装问题,首先尝试解读错误,再使用  ./configure --help  不行再上Stack overflo ...