信号量(Semaphore)

Semaphore 一般译作 信号量,它也是一种线程同步工具,主要用于多个线程对共享资源进行并行操作的一种工具类。它代表了一种许可的概念,是否允许多线程对同一资源进行操作的许可,使用 Semaphore 可以控制并发访问资源的线程个数。

Semaphore 的使用场景

1、主要用于流量控制,比如数据库连接,同时使用的数据库连接会有数量限制,数据库连接不能超过一定的数量,当连接到达了限制数量后,后面的线程只能排队等前面的线程释放数据库连接后才能获得数据库连接。
2、 信号量:是进程间(线程间)同步用的,一个进程(线程)完成了某一个动作就通过信号量告诉别的进程(线程),别的进程(线程)再进行某些动作。有二值和多值信号量之分。

它与的互斥锁区别是 互斥锁:是线程间互斥用的,一个线程占用了某一个共享资源,那么别的线程就无法访问,直到这个线程离开,其他的线程才开始可以使用这个共享资源。可以把互斥锁看成二值信号量。

引发的问题

信号量存在的优先级翻转问题

优先级反转,是指在使用信号量时,可能会出现的这样一种不合理的现象,即:

高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。-- 从现象上来看,好像是中优先级的任务比高优先级任务具有更高的优先权。

具体来说:当高优先级任务正等待信号量(此信号量被一个低优先级任务拥有着)的时候,一个介于两个任务优先之间的中等优先级任务开始执行——这就会导致一个高优先级任务在等待一个低优先级任务,而低优先级任务却无法执行类似死锁的情形发生。

主要方法

Semaphore(1, 4):默认运行信号量之后就可以释放一条线程进入临界资源。手动设置Release的一次最大个数是4条线程,临界区最大的线程数是4.当一次释放的线程超过等待的资源数就会报错

WaitOne()阻塞线程,等灯来

Release(N) 同时放行条线程进入资源区,最大不能超过初始化设定的maximumCount

Close()释放所有

使用方式1

有10个线程,同时只执行4条线程,每完成一个就Release一个,等待中的就补上去

代码如下:

该代码会正常执行完成,并且释放所有线程,因为初始化话new Semaphore(1, 4)时候已经设置默认释放一条线程,这条线程执行完成后road.Release();又释放下一条。依次释放完所有线程。
Semaphore road = new Semaphore(1, 4);
for(int i = 0; i < 10; i++)
{
new Thread(obj =>
{
int se = (int)obj;
Console.WriteLine(se);
road.WaitOne(); Console.WriteLine("release{0}",obj);
road.Release();//该线程执行完毕,后再释放一个线程
} ).Start(i); }
Thread.Sleep(1000);
//该代码会正常执行完成,并且释放说有线程,因为初始化话new Semaphore(1, 4)时候已经设置默认释放一条线程,这条线程执行完成后road.Release();又释放下一条。依次释放完所有线程。

另外,信号量是内核对象可以再多个进程中使用。可以给信号量设置一个名称,这个名称是操作系统可见的,因此,可以使用这些信号量来协调跨进程边界的资源使用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace Semaphore2
{
class Program
{
static void Main(string[] args)
{
Semaphore seamphore = new Semaphore(5, 5, "SemaphoreExample"); seamphore.WaitOne();
Console.WriteLine("Seamphore 1");
seamphore.WaitOne();
Console.WriteLine("Seamphore 2");
seamphore.WaitOne();
Console.WriteLine("Seamphore 3"); Console.ReadLine();
seamphore.Release(3);
}
}
} 复制代码

运行两个这样的程序,你将看到这样的结果,在第二个运行的示例中,会将线程阻塞在第三个信号量

最新文章

  1. Fresco从配置到使用(最高效的图片加载框架)
  2. logrotate机制与原理[转载]
  3. 【转载】阎焱:90后创业是扯淡 大量O2O和P2P公司濒临倒闭
  4. C#事件快捷设置
  5. 什么是RFC
  6. 基于C++/Lua的游戏服务器如何实现?
  7. 【原】visual studio添加现有文件夹的方法
  8. .Net 接连 Oracle 数据库(Winform)
  9. 关于a[i]++和a[i++]说明
  10. 搭建环境-Monkeyrunner-自动化测试工具
  11. Redis数据结构之ziplist
  12. MySQL使用root权限创建用户并授权
  13. MySQL设置global变量和session变量
  14. ubuntu系统安装微信小程序开发工具
  15. OpenGL初学:安装配置与第一个程序
  16. “数学口袋精灵”App的第三个Sprint计划(总结与团队感悟)----开发日记
  17. ThinkPHP中如何获取指定日期后工作日的具体日期
  18. 雷林鹏分享:XML 相关技术
  19. Windows编译Opencv
  20. phpstorm——配置interpreter——找了半天终于ok

热门文章

  1. 判断jquery类库是否加载,如未加载则加载。
  2. elasticsearch源码分析及插件开发
  3. linux用户密码过期导致命令执行失败
  4. Visualizing and Understanding Convolutional Networks论文复现笔记
  5. django之定义统一返回数据格式与GET/POST装饰器
  6. ESP32:蓝牙BLE控制M3508电机
  7. Caffeine缓存 最快缓存 内存缓存
  8. react 局部更新的关键算法 DOM diff算法
  9. Mysql8.0主从配置
  10. SpringMVC主要组件