Semaphore:信号量
命名空间:System.Threading
限制可同时访问某一资源或资源池的线程数。
信号量非常类似于互斥,其区别是信号量可以同时有多个线程使用。信号量是一种计数的互斥锁定。使用信号量,可以定义允许同时访问受保护和锁定的资源的线程个数。如果需要限制可以访问可用资源的线程数量,信号量就很有用。
构造函数
构造函数 | 描述 |
---|---|
Semaphore(Int32, Int32) | 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数。 |
Semaphore(Int32, Int32, String) | 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,根据需要指定系统信号灯对象的名称。 |
Semaphore(Int32, Int32, String, Boolean) | 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,还可以选择指定系统信号量对象的名称,以及指定一个变量来接收指示是否创建了新系统信号量的值。 |
Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity) | 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,可以选择指定系统信号量对象的名称,指定一个变量来接收指示是否创建了新系统信号量的值,以及指定系统信号量的安全访问控制。 |
方法
方法 | 描述 |
---|---|
Close() | 释放由当前 WaitHandle 占用的所有资源。 |
Dispose() | 释放 WaitHandle 类的当前实例所使用的所有资源。 |
OpenExisting(String) | 打开指定名称为信号量(如果已经存在)。 |
OpenExisting(String, SemaphoreRights) | 用安全访问权限打开指定名称为信号量(如果已经存在)。 |
Release() | 退出信号量并返回前一个计数。 |
Release(Int32) | 以指定的次数退出信号量并返回前一个计数。 |
WaitOne() | 阻止当前线程,直到当前 WaitHandle 收到信号。 |
WaitOne(Int32) | 阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。 |
WaitOne(Int32, Boolean) | 阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。 |
属性
属性 | 描述 |
---|---|
Handle | 获取或设置本机操作系统句柄。 |
SafeWaitHandle | 获取或设置本机操作系统句柄。 |
字段
字段 | 描述 |
---|---|
WaitTimeout | 指示在任何等待句柄终止之前 WaitAny(WaitHandle[], Int32, Boolean) 操作已超时。 此字段为常数。 |
具体详细信息请点击微软官方链接:Semaphore
示例:
static void Main(string[] args)
{
int taskCount = 6;
int semaphoreCount = 3;
var semaphore = new Semaphore(semaphoreCount, semaphoreCount);
var tasks = new Task[taskCount];
for (int i = 0; i < taskCount; i++)
{
tasks[i] = Task.Run(() => TaskRuning(semaphore));
}
Task.WaitAll(tasks);
Console.WriteLine("所有任务以完成!");
Console.ReadKey();
}
static void TaskRuning(Semaphore s)
{
bool isCompleted = false;
while(!isCompleted)
{
if(s.WaitOne(600))
{
try
{
Console.WriteLine("Task {0} 锁定这个信号",Task.CurrentId);
Thread.Sleep(1000);
}
finally
{
Console.WriteLine("Task {0} 释放这个信号", Task.CurrentId);
s.Release();
isCompleted = true;
}
}
else
{
Console.WriteLine("超时任务 :Task {0} 等待下一次",Task.CurrentId);
}
}
}
运行输出:
示例说明:
创建了6个任务和一个计数为3的信号量。在 Semaphore类的构造函数中,定义了锁定个数的计数为3(可以同时授予的信号量的最大请求数),它是信号量构造函数的第二个参数来获得。还定义了最初释放的锁定数(最大并发入口数,构造函数第一个参数)。如果第一个参数值小于第二个参数值,它们的差就是已经分配线程的计数值。可以理解为:第一个参数为剩余机会数,第二个参数为总的机会数。第一个参数必须小于或等于第二个参数。
与互斥锁一样,也可 以给信号量指定名称,使之在不同之间的进程共享。这里没有指定名称,所以只能在当前进程中使用。程序启动 创建 Semaphore对象,启动6个任务,都给相同的信号量。然后开始异常执行任务。但是每次只能进去3个线程的任务。其他要等待前面的任务释放信号后再依次进入。
**信号量控制的只是线程同步的量,而不管顺序。**这个例子来说线程控制的就是线程同步量为3,也就是同时并发的线程数量为3个,至于是哪个先哪个后不是由这里的信号量决定的。
SemaphoreSlim类 是对较短等待时间进行优化的轻型版本,用法类似,感兴趣的可以自己试一下。