[平行處理 - 3] Parallel.For + Lock + SemaphoreSlim

  • 29933
  • 0
  • C#
  • 2018-04-09

Lock是一個一次只能有一個人進去的區域

但如果我有自己的上限值 ex: 一次可以 3 個人一起進入某個區域

那我該怎麼做呢?

答案就是使用 SemaphoreSlim

 

考慮以下情境

1. 有 9 個人想買票

2. 售票亭一次最多同時 3 人進去買

3. 但票只有 5 張

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication5
{
    /// <summary>
    /// 示範 Parallel.For + SemaphoreSlim
    /// </summary>
    class Program
    {
        static Object _lock = new Object();
        static SemaphoreSlim _sem = new SemaphoreSlim(3); //最多可以 3 人一起買票
        static int ticketQty = 5;                         //而票只有 5 張

        static void Main()
        {
            Parallel.For(1, 10, i =>                      //但有 9 個人想買
            {
                Thread.Sleep(300);
                BuyTicket(i.ToString("00"));
            });

            Console.WriteLine("----銷售一空----");
            Console.ReadLine();
        }

        static void BuyTicket(string id)
        {
            Console.WriteLine(id + " 進入售票亭");

            _sem.Wait();
            if (HasTicket())
            {
                Console.WriteLine(id + " 買票中 ( 要花 5 秒 )");
                Thread.Sleep(5000);
                Console.WriteLine(id + " 付款離開");
            }
            else
            {
                Console.WriteLine(id + " 沒票直接離開");
            }
            _sem.Release();
        }

        static bool HasTicket()
        {
            if (ticketQty <= 0) return false;

            lock (_lock)
            {
                if (ticketQty <= 0) return false;

                ticketQty--;
                return true;
            }
        }
    }
}