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(); }