Semaphores
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
最多只允许三个线程,因此我们可以确保数据库连接数不会超过限制。