Semaphore,中文译为信号灯。在C#中,它可以允许指定数量的线程同时访问共享资源,而其他的线程必须等待。
即现在有5个线程同时运行,但Semaphore指定2个线程可以同时访问某一共享资源。当执行Semaphore.Wait()时,只有2个线程可以同时进入访问共享资源,而其他三个线程则阻塞等待,直到某一个线程执行Semaphore.Release()时,就会释放一个阻塞的线程。
即同时访问共享资源的线程数量必须小于或等于Semaphore指定的数量。
SemaphoreSlim是Semaphore的轻量型实现,即占用资源没有Semaphore多。
Semaphore可以实现进程和线程并发同步;
SemaphoreSlim只能实现线程的并发同步。
代码如下:
public static int Counter = 0; //指定2个线程可以同时访问共享资源 static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2); static void WorkOnSemaphore(string threadName, int seconds) { Console.WriteLine($"{threadName} 正在等待中..."); //阻塞指定数量之外的线程 semaphoreSlim.Wait(); Console.WriteLine($"{threadName} 执行中..."); //因为我们指定了2个线程可以同时访问,在此做一个标记,如果是2个线程之外的,必须等待 Interlocked.Increment(ref Counter); if(Counter%2==0) Console.WriteLine("其他线程等待中..."); //Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine($"{threadName} 执行完毕!"); semaphoreSlim.Release(); }
Main方法中的代码如下:
for (int i = 0; i < 5; i++) { string threadName = $"thread_{i}"; int seconds = 2 + 2 * i; var thread = new Thread(delegate () { WorkOnSemaphore(threadName, seconds); }); thread.Start(); }
结果:
通过结果可以看出,每次只能有2个线程能同时访问,而其他的线程则被阻塞等待。
参考文献:https://docs.microsoft.com/zh-cn/dotnet/standard/threading/semaphore-and-semaphoreslim