2014年6月18日水曜日

セマフォ!Semaphore!スレッドの実行数指定

セマフォの初期実行数0にハマったのでここに記す。
0だとReleaseしない限りWaitOneでtrue返らないなんて。
0からカウントアップして最大実効数まで使えると思ってたよ

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

namespace Project4
{
    class Program
    {
        //セマフォ
        //スレッドの同時実効数を設定。この場合初期実行数0, 最大実効数2
        static Semaphore _sem = new Semaphore(0, 2);

        static void Main(string[] args)
        {
            //労働者5人を働かせる
            for (var i = 0; i < 5; i++)
            {
                Emploee emp = new Emploee(i + 1);
                emp.SetSemaphore = _sem;
                emp.IsWorking = true;

                Thread t = new Thread(new ThreadStart(emp.working));

                t.Start();
            }

            Thread.Sleep(500);
            
            //初期実行数0なのでReleaseしないとWaitOneでシグナルを取得できない
            _sem.Release(2);
        }

    }   

    /// 
    /// 従業員。働け
    /// 
    class Emploee
    {
        #region member
        /// セマフォ
        private Semaphore _sem;

        /// 労働者番号
        private int _number;
        #endregion

        #region Property
        /// セマフォ
        public Semaphore SetSemaphore
        {
            set { this._sem = value; }
        }

        /// 労働中?
        public bool IsWorking { get; set; }
        #endregion

        public Emploee(int number)
        {
            this.IsWorking = false;
            this._number = number;
        }

        public void working()
        {
            //働いてもらう
            while (this.IsWorking) {

                //指定ミリ秒数毎に監視。
                //セマフォ.WaitOneで実行数 -1。実行数が0ならWaitOneでfalseが返る
                if (this._sem.WaitOne(300))
                {
                    System.Diagnostics.Debug.WriteLine(string.Format("わたしは{0}番の労働者です。労働しています。", this._number));
                    Thread.Sleep(200);

                    //働いたらあがっていい
                    this.IsWorking = false;
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine(string.Format("わたしは{0}番の労働者です。待機中です。", this._number));
                }
            }

            //開放するとセマフォの実行数 + 1
            this._sem.Release();
        }
    }
}


実行結果

わたしは2番の労働者です。待機中です。
わたしは4番の労働者です。待機中です。
わたしは5番の労働者です。待機中です。
わたしは1番の労働者です。待機中です。
わたしは3番の労働者です。待機中です。
わたしは2番の労働者です。労働しています。
わたしは3番の労働者です。労働しています。
わたしは4番の労働者です。待機中です。
わたしは1番の労働者です。待機中です。
わたしは5番の労働者です。待機中です。
わたしは5番の労働者です。労働しています。
わたしは1番の労働者です。労働しています。
わたしは4番の労働者です。労働しています。

0 件のコメント:

コメントを投稿