Semaphore 继承自System.Threading.WaitHandle
,因此,你可以调用WaitOne
()
,视情况需要也可以调用WaitAny()
,WaitAll()
,SignalAndWait()
等函数。
Semaphore 就其用法而言,与夜店(国外)的运营方式很像。夜店有容量上限,由门卫确保,当满员时,外面的人不允许再进入,直到有一个人出来,才能有一个人进入。
下面我们通过一个例子来说明,初始设置Semaphore 可以处理两个并发请求,最大容量为5个并发请求:
using System; using System; using System.Threading; namespace SemaphoreTest { class Program { //initial count to be satified concurrently = 2 //maximum capacity = 5 static Semaphore sem = new Semaphore(2, 5); static void Main(string[] args) { for (int i = 0; i < 10; i++) { new Thread(RunThread).Start("T" + i); } Console.ReadLine(); } static void RunThread(object threadID) { while (true) { Console.WriteLine(string.Format( "thread {0} is waiting on Semaphore", threadID)); sem.WaitOne(); try { Console.WriteLine(string.Format( "thread {0} is in the Semaphore, and is now Sleeping", threadID)); Thread.Sleep(100); Console.WriteLine(string.Format( "thread {0} is releasing Semaphore", threadID)); } finally { //Allow another into the Semaphore sem.Release(); } } } } }结果如下:
下面的代码中,用Semaphore
来限制接入数据库的连接的数量,最多可以接受3个并发请求。
using System; using System.Threading; using System.Data; using System.Data.SqlClient; namespace SemaphoreTest { /// <summary> /// This example shows partially completed skeleton /// code for consuming a limited resource, such as a /// DB connection using a Semaphore /// /// NOTE : THIS CODE WILL NOT RUN, ITS INCOMPLETE /// DEMO ONLY CODE /// </summary> class RestrictedDBConnectionStringAccessUsingSemaphores { //initial count to be satified concurrently = 1 //maximum capacity = 3 static Semaphore sem = new Semaphore(1, 3); static void Main(string[] args) { //start 5 new threads that all require a Database connection //but as a DB connection is limited to 3, we use a Semaphore //to ensure that the number of active connections will never //exceed the total allowable DB connections new Thread(RunCustomersThread).Start("ReadCustomersFromDB"); new Thread(RunOrdersThread).Start("ReadOrdersFromDB"); new Thread(RunProductsThread).Start("ReadProductsFromDB"); new Thread(RunSuppliersThread).Start("ReadSuppliersFromDB"); Console.ReadLine(); } static void RunCustomersThread(object threadID) { //wait for the Semaphore sem.WaitOne(); //the MAX DB connections must be within its limited //so proceed to use the DB using (new SqlConnection("<SOME_DB_CONNECT_STRING>")) { //do our business with the database } //Done with DB, so release Semaphore which will //allow another into the Semaphore sem.Release(); } static void RunOrdersThread(object threadID) { //wait for the Semaphore sem.WaitOne(); //the MAX DB connections must be within its limited //so proceed to use the DB using (new SqlConnection("<SOME_DB_CONNECT_STRING>")) { //do our business with the database } //Done with DB, so release Semaphore which will //allow another into the Semaphore sem.Release(); } static void RunProductsThread(object threadID) { //wait for the Semaphore sem.WaitOne(); //the MAX DB connections must be within its limited //so proceed to use the DB using (new SqlConnection("<SOME_DB_CONNECT_STRING>")) { //do our business with the database } //Done with DB, so release Semaphore which will //allow another into the Semaphore sem.Release(); } static void RunSuppliersThread(object threadID) { //wait for the Semaphore sem.WaitOne(); //the MAX DB connections must be within its limited //so proceed to use the DB using (new SqlConnection("<SOME_DB_CONNECT_STRING>")) { //do our business with the database } //Done with DB, so release Semaphore which will //allow another into the Semaphore sem.Release(); } } }
从这个例子,我们可以看出Semaphore
最多只允许三个线程,因此我们可以确保数据库连接数不会超过限制。