1、限制可同时访问某一资源或资源池的线程数。
SemaphoreSlim为Semaphore 的轻量替代
使用:实例化一个初始值0最大值3
private static Semaphore _pool; _pool = new Semaphore(0, 3);
_pool.Release(3);
释放三个线程访问
如下代码:
using System; using System.Threading; public class Example { // A semaphore that simulates a limited resource pool. //模拟限制资源池 private static Semaphore _pool; // A padding interval to make the output more orderly. private static int _padding; public static void Main() { // Create a semaphore that can satisfy up to three // concurrent requests. Use an initial count of zero, // so that the entire semaphore count is initially // owned by the main program thread. ////创建一个最多可以满足三个的信号量 //并发请求。 使用初始计数为零, //这样最初的整个信号量计数 //由主程序线程拥有。 _pool = new Semaphore(0, 3); // Create and start five numbered threads. //创建5个线程,先允许三个访问 for(int i = 1; i <= 5; i++) { Thread t = new Thread(new ParameterizedThreadStart(Worker)); // Start the thread, passing the number. // t.Start(i); } // Wait for half a second, to allow all the // threads to start and to block on the semaphore. // Thread.Sleep(500); // The main thread starts out holding the entire // semaphore count. Calling Release(3) brings the // semaphore count back to its maximum value, and // allows the waiting threads to enter the semaphore, // up to three at a time. //允许三个进入访问 Console.WriteLine("Main thread calls Release(3)."); _pool.Release(3); Console.WriteLine("Main thread exits."); } private static void Worker(object num) { // Each worker thread begins by requesting the // semaphore. Console.WriteLine("Thread {0} begins " + "and waits for the semaphore.", num); _pool.WaitOne(); // A padding interval to make the output more orderly. int padding = Interlocked.Add(ref _padding, 100); Console.WriteLine("Thread {0} enters the semaphore.", num); // The thread's "work" consists of sleeping for // about a second. Each thread "works" a little // longer, just to make the output more orderly. // Thread.Sleep(1000 + padding); Console.WriteLine("Thread {0} releases the semaphore.", num); Console.WriteLine("Thread {0} previous semaphore count: {1}", num, _pool.Release()); } }
using System; using System.Threading; using System.Threading.Tasks; public class Example { private static SemaphoreSlim semaphore; // A padding interval to make the output more orderly. private static int padding; public static void Main() { // Create the semaphore. semaphore = new SemaphoreSlim(0, 3); Console.WriteLine("{0} tasks can enter the semaphore.", semaphore.CurrentCount); Task[] tasks = new Task[5]; // Create and start five numbered tasks. for(int i = 0; i <= 4; i++) { tasks[i] = Task.Run( () => { // Each task begins by requesting the semaphore. Console.WriteLine("Task {0} begins and waits for the semaphore.", Task.CurrentId); semaphore.Wait(); Interlocked.Add(ref padding, 100); Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId); // The task just sleeps for 1+ seconds. Thread.Sleep(1000 + padding); Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.", Task.CurrentId, semaphore.Release()); } ); } // Wait for half a second, to allow all the tasks to start and block. Thread.Sleep(500); // Restore the semaphore count to its maximum value. Console.Write("Main thread calls Release(3) --> "); semaphore.Release(3); Console.WriteLine("{0} tasks can enter the semaphore.", semaphore.CurrentCount); // Main thread waits for the tasks to complete. Task.WaitAll(tasks); Console.WriteLine("Main thread exits."); } } // The example displays output like the following: // 0 tasks can enter the semaphore. // Task 1 begins and waits for the semaphore. // Task 5 begins and waits for the semaphore. // Task 2 begins and waits for the semaphore. // Task 4 begins and waits for the semaphore. // Task 3 begins and waits for the semaphore. // Main thread calls Release(3) --> 3 tasks can enter the semaphore. // Task 4 enters the semaphore. // Task 1 enters the semaphore. // Task 3 enters the semaphore. // Task 4 releases the semaphore; previous count: 0. // Task 2 enters the semaphore. // Task 1 releases the semaphore; previous count: 0. // Task 3 releases the semaphore; previous count: 0. // Task 5 enters the semaphore. // Task 2 releases the semaphore; previous count: 1. // Task 5 releases the semaphore; previous count: 2. // Main thread exits.