一、Semaphore
Semaphore(信号量)是一种轻量级替代方案,它限制了可以同时访问资源或资源池的线程数。
命名空间:System.Threading
平台提供了Semaphore和SemaphoreSlim。
Semaphore:类可以命名,使用系统范围内的资源,允许在不同进程之间同步
SemaphoreSlim:是对较短等待时间进行了优化的轻型版本。
与互斥的区别:信号量可同时由多个线程使用。信号量是一种计数的互斥锁定。使用信号量,可以允许定义同时访问受旗语锁定保护的资源线程个数。
二、信号量的类型
局部信号量 | 命名系统信号量 | |
说明 | 本地信号 | 整个操作系统 |
适用于 | 进程内 | 进程内和进程间可以使用 |
类 | SemaphoreSlim | Semaphore |
三、应用场景:如果有若干个访问资源,但是访问资源的数量大于资源个数,就可以这个类Semaphore。
举个常见的例子:食堂的洗碗池水龙头和洗碗的人数,假设食堂有5个水龙头,而洗碗的人数多余水龙头的若干倍,这样水龙头就是我们需要抢夺的资源了,
水龙头固定,那么最多只能有这几个人共同使用。
下面我们就用SemaphoreSlim来实现上面的应用场景。
class Program
{
static void Main(string[] args)
{
int taskCount = 6;
int SemaphoreCount = 3;
WriteLine($"有{taskCount}人来使用水龙头,水房总共有{SemaphoreCount}个水龙头");
var semaphore = new SemaphoreSlim(SemaphoreCount, SemaphoreCount);
var tasks = new Task[taskCount];
for (int i = 0; i < taskCount; i++)
{
tasks[i] = Task.Run(() => Washing(semaphore));
}
Task.WaitAll(tasks);
WriteLine(" 所有人都使用完了,全部资源释放。 ");
ReadLine();
}
public static void Washing(SemaphoreSlim semaphore)
{
bool isCompleted = false;
while(!isCompleted)
{
if(semaphore.Wait(600))
{
try
{
WriteLine($"{Task.CurrentId} 正在使用水龙头 ,锁定了资源。");
Task.Delay(2000).Wait();
}finally
{
WriteLine($"{Task.CurrentId} 已经使用完了水龙头,释放了资源。");
semaphore.Release();
isCompleted = true;
}
}
else
{
WriteLine($"{Task.CurrentId}; 正在等待资源 。");
}
}
}
}