您的位置:首页 > Web前端

Thread-Safety with the Semaphores Class(Synchronization of .net)

2012-06-02 21:38 375 查看

Semaphores

A Semaphore inherits from
System.Threading.WaitHandle
; as such, it has the
WaitOne()
method. You are also able to use the static
System.Threading.WaitHandle
,
WaitAny()
,
WaitAll()
,
SignalAndWait()
methods for more complex tasks.

semaphores model like this. see below:



I read something that described a Semaphore being like a nightclub. It has a certain capacity, enforced by a bouncer. When full, no more people can enter the club, until one person leaves the club, at which point one more person may enter the club.

Let's see a simple example, where the Semaphore is set up to be able to handle two concurrent requests, and has an overall capacity of 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(); } } } }}

Which results in something similar to this:



This example does show a working example of how a
Semaphore
can be used to limit the number of concurrent threads, but it's not a very useful example. I will now outline some partially completed code, where we can use a
Semaphore
to limit the number of threads trying to access a database with a limited number of connections available. The database can only accept a maximum of three concurrent connections. As I say, this code is incomplete, and does not work in its current state; it's for demonstration purposes only, and is not part of the attached demo app.
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(); } }}

From this small example, it should be clear that the
Semaphore
only allows a maximum of three threads (which was set in the
Semaphore
constructor), so we can be sure that the database connections will also be kept within limit.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐