.Net下的线程同步:Part 2 of N--(Semaphores)

Semaphores

Semaphore 继承自System.Threading.WaitHandle,因此,你可以调用WaitOne(),视情况需要也可以调用WaitAny(),WaitAll(),SignalAndWait()等函数。

.Net下的线程同步:Part 2 of N--(Semaphores)_第1张图片

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();
                }
            }
        }
    }
}
结果如下:

.Net下的线程同步:Part 2 of N--(Semaphores)_第2张图片

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


你可能感兴趣的:(thread,.net,String,object,Semaphore,database)