C# スレッドの同期とスレッド プールの簡単な分析

黄舟
リリース: 2017-03-03 13:34:49
オリジナル
1503 人が閲覧しました

C# スレッド同期とスレッド プール

例は非常に簡単で、5 つのスレッドを用意し、各スレッドが同時にコンソールに数値を出力し、出力結果を観察します。

コードの説明:

////Thread list

private static List<Thread> _threadList;
 
 
        static voidMain(string[] args)
        {
            Program._threadList= new List<Thread>();
            ////附加5个线程
            for (inti = 0; i < 5; i++)
            {
                Program.AppendThread();
            }
 
            ////开始执行所有测试线程
            Program.ExecuteThread();
 
            ////按任意键退出
            Console.ReadLine();
        }
 
        /// <summary>
        /// 将新的测试线程附加到测试线程列表,线程执行逻辑就是输出10个数字
/// 注意初始化的时候设置为后台线程了,这样可以保证主线程退出的时候其他线/// 程自动退出
        /// </summary>
        public staticvoid AppendThread()
        {
            Program._threadList.Add(newThread(new ThreadStart(
                () =>
                {
                   for (int i = 0; i < 10; i++)
                   {
                       Console.WriteLine(i);
                   }
                })){ IsBackground = true });
        }
 
        /// <summary>
        /// 开始执行所有测试线程
        /// </summary>
        public staticvoid ExecuteThread()
        {
            foreach(Thread t in _threadList)
            {
                t.Start();
            }
        }
ログイン後にコピー

実行結果を観察すると、結果は次のとおりであることがわかります:

結果によると(数値の出力は不規則)、ネジ干渉が発生していることが分かります。戦略は、スレッド同期用の同期メンバーを追加することです:

   /// <summary>
        /// 多线程同步的对象
        /// </summary>
        private static object _syncObj = new object();
另外,在线程执行的地方加锁:
Program._threadList.Add(newThread(new ThreadStart(
                () =>
                {
                    lock (_syncObj)
                    {
                        for (int i = 0; i < 10;i++)
                        {
                            Console.WriteLine(i);
                        }
                    }
 
                })) { IsBackground = true });
ログイン後にコピー

観察結果:

Lock キーワードを通じて、マルチスレッド同期変数をロックすると実際に同期できることがわかります。スレッドをサイズ化します。

次に 2 番目の方法を見てみましょう:

同期に Monitor キーワードを使用します。コード:

Monitor.Enter(_syncObj);
                   try
                   {
                       for (int i = 0; i < 10; i++)
                       {
                            Console.WriteLine(i);
                       }
                   }
                   finally {
                       Monitor.Exit(_syncObj);
                   }
ログイン後にコピー

結果を表示すると、スレッドが同期されていることがわかります。

3 番目の方法:

次に、コードをリファクタリングし、新しい ThreadManager クラスを作成し、クラスのすべての責任をそこに移動します:

class ThreadManager
    {
        /// <summary>
        /// 线程列表
        /// </summary>
        private staticList<Thread> _threadList;
 
        staticThreadManager()
        {
           _threadList = new List<Thread>();
        }
 
        /// <summary>
        /// 附加新线程
        /// </summary>
        public staticvoid AppendThread()
        {
            ThreadManager._threadList.Add(newThread(new ThreadStart(
                () =>
                {
                   for (int i = 0; i < 10; i++)
                   {
                       Console.WriteLine(i);
                   }
 
                })){ IsBackground = true });
        }
 
        /// <summary>
        /// 开始执行所有线程
        /// </summary>
        public staticvoid ExecuteThread()
        {
            foreach(Thread t in _threadList)
            {
                t.Start();
            }
        }
    }
ログイン後にコピー

Main 関数によって呼び出されるコードに対応する変更を加えます:

static voidMain(string[] args)
        {
            ////附加5个线程
            for (int i = 0; i < 5; i++)
            {
                ThreadManager.AppendThread();
            }
 
            ////开始测试
            ThreadManager.ExecuteThread();
 
            ////按任意键继续
            Console.ReadLine();
        }
ログイン後にコピー

スレッド同期のための処理が行われないため、結果はスレッドが同期していないことを確実に推測できます:

次に、ThreadManager クラスに機能を追加します: [Synchronization] もう一度実行してください。最後に、スレッドが同期されていることがわかります。これは、スレッド同期の 4 番目のソリューションです。使用するのは非常に簡単ですが、最初に実行ロジックをクラスに配置する必要があります。このクラスのメソッドはすべてスレッドセーフであるため、パフォーマンスは比較的非効率的です

スレッドを同期する他の方法はありますか?答えは「はい」です。それが 4 番目のメソッド スレッド プールです。

それでは、スレッド プールを使用して実装する方法を見てみましょう:

  static void Main(string[]args)
        {
/////定义一个waitCallback对象,并定义它的行为,就是向控制台输出十个数字同时可以传递/////一个参数(这个参数是可选的)
                       WaitCallback work = new WaitCallback((o)=>
            {
                for(int i = 0; i < 10; i++)
                {
                   Console.WriteLine(i);
                }
            });
 
            ////执行5次
            for (inti = 0; i < 5; i++)
            {
/////如果这里需要传递参数,可以调用另一个重载方法
                ThreadPool.QueueUserWorkItem(work);
            }
 
            ////按任意键继续
            Console.ReadLine();
        }
ログイン後にコピー
これでロジックは完了しましたか?はい、実行後に結果が確認できます。スレッドは同期されています。

マルチスレッドには他にどのような利点がありますか?

  • スレッド プールを使用すると、スレッドの作成、開始、停止の回数が減り、効率が向上します

  • スレッド プールを使用すると、マルチスレッド アーキテクチャではなくビジネス ロジックに集中できます (ただし、場合によっては手動で実行する必要があります)。スレッド管理を最初に使用する必要があります)

  • フォアグラウンド スレッドが必要な場合、または優先レベルを設定する場合、またはスレッド プール内のスレッドが常にバックグラウンド スレッドであり、その優先順位がデフォルトである場合

  • 必要な場合。 a スレッドの ID が固定されているため、スレッドの終了、一時停止、または名前による検出が簡単になります。

上記は、C# スレッド同期とスレッド プールの簡単な分析です。さらに関連するコンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。



関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!