ほとんどの場合、スレッド化が必要なアプリケーションがあります。ほとんどの場合、各スレッドの実行前にオブジェクトが更新されたため、エラーや間違った値が発生します。
オブジェクトをスレッドセーフにし、オブジェクトが各スレッドに対して正しいことを確認する方法について何か提案はありますか? 変数を作成する必要がありますstatic
か?
ほとんどの場合、スレッド化が必要なアプリケーションがあります。ほとんどの場合、各スレッドの実行前にオブジェクトが更新されたため、エラーや間違った値が発生します。
オブジェクトをスレッドセーフにし、オブジェクトが各スレッドに対して正しいことを確認する方法について何か提案はありますか? 変数を作成する必要がありますstatic
か?
最初にすべきことは、マルチスレッドで解決したい問題のHappens-Before グラフを描くことです。デザインを描くことができない場合、それは複雑すぎます。
たとえば、これは int の 2 つの配列を取り、すべての要素の合計を出力するメソッドの事前発生グラフです。
事前発生グラフを作成すると、他の何かの前に何が発生する必要があるかを確認するのは非常に簡単ですが、さらに重要なことは、他の何かの前に何が発生する必要がないかを示します。
この例では、array1 と array2 の両方の合計を同時に取得できます。また、相互に依存していないため、sum2 と同時に sum1 を取得することもできます。TotalSum1 への合計の追加は、どちらの順序でも行うことができます (ただし、別の段階で同時に追加を行うことはできないため、追加ステップを固定する必要があります)。
C# .net 4.0 には、並列プログラミングに役立つ多くの機能があります。
この本、Parallel Programming with Microsoft .Netをお勧めします。左側のブックマークを使用してナビゲートしてください。ループ、タスク、集約、フューチャー、およびパイプラインの並列パターンをカバーしています。
上記の例では、Task1 を使用して Array1 を取得し、Task2 を使用して Array2 を取得します。次に、それらの両方で、配列の合計に対して Parallel.For ループに組み込まれた集約パターンを使用します。ロックを使用する必要があります。または Interlocked.Add を使用して subTotals を累積し、タスクが終了して結果を返すのを待ちます。
便利なパターン:
便利なツール:
基本的に、まず問題を理解してから、それを解決するためのツール/パターンを選択してください。
スレッド セーフにする必要があるリソースに対して lock ステートメントを使用することを検討してください。
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
これが私の最初のステップです。また、Monitor クラスを調べることもできます。
http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx
これらは、同時操作中にリソースを保護するための 2 つの基本的な方法です。ミューテックス、センパフォア、条件付き読み取り/書き込みロックなど、他にも多くの方法があります。
ここから始めてください:マルチスレッドのためのデータの同期
基本的に、ミューテックスを使用する必要があります。.NET では、すべてのオブジェクトがミューテックスとして機能できるため、任意のオブジェクトでlock キーワードを使用して相互排他を確保できます。