ThreadSafety with the Semaphores Class(Synchronization of .net)

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.WaitHandleWaitAny()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 aSemaphore 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. 
原文地址:https://www.cnblogs.com/malaikuangren/p/2532249.html