私は読んでいて、プロパティでsynclockを使用する必要があるかどうかについて矛盾する答えを得ています。
インスタンス オブジェクトのスレッド間でプロパティを取得/設定する必要があるマルチスレッド アプリケーションがあります。現在、同期クロックを使用せずに実装されており、これまでのところ問題に気づいていません。一般的な静的メソッドで synclock を使用していますが、インスタンス クラスを適切かつスレッド セーフな方法で実装したいと考えています。
どんなフィードバックでも大歓迎です。
私は読んでいて、プロパティでsynclockを使用する必要があるかどうかについて矛盾する答えを得ています。
インスタンス オブジェクトのスレッド間でプロパティを取得/設定する必要があるマルチスレッド アプリケーションがあります。現在、同期クロックを使用せずに実装されており、これまでのところ問題に気づいていません。一般的な静的メソッドで synclock を使用していますが、インスタンス クラスを適切かつスレッド セーフな方法で実装したいと考えています。
どんなフィードバックでも大歓迎です。
経験則として、次の条件のいずれかに該当する場合はロックする必要があります。
その場合、おそらく、それらのフィールドにアクセスするすべてのメソッドまたはプロパティをロックする必要があります。
編集:クラス内でロックするだけでは十分ではないことに注意してください。必要なのは、論理操作全体で問題が発生しないようにすることです。
@Bevan が指摘しているように、呼び出しコードがオブジェクトに複数回アクセスする必要がある場合、クライアント コードは、別のスレッドが「間に」入らないようにするために、その作業の全期間にわたってオブジェクトに対する独自のロックを取得する必要があります。アクセスし、そのロジックを汚します。
また、一度に複数のロックを解除する必要がある場合は、常に同じ順序で取得するように注意する必要があります。スレッド 1 がインスタンス A をロックしてインスタンス B をロックしようとし、スレッド 2 がインスタンス B をロックしてインスタンス A をロックしようとすると、両方のスレッドがスタックして先に進めなくなります。つまり、デッドロックが発生します。
個々のメソッドをロックで囲むだけでは、オブジェクトをスレッドセーフにすることはできません。最終的に行うことは、オブジェクトへのアクセスをシリアル化する (遅くする) ことだけです。
このマイナーな例を考えてみましょう:
var myObject = ...
var myThreadSafeList = ...
if (!myThreadSafeList.Contains(myObject))
{
myThreadSafeList.Add(myObject);
}
myThreadSafeList ですべてのメソッドがロックされていても、 と の呼び出しの間に別のスレッドがリストの内容を変更できるため、これはスレッドセーフではありません。Contains()
Add()
このリストの場合、追加のメソッドが必要です: AddIfMissing()
:
var myObject = ...
var myThreadSafeList = ...
myThreadSafeList.AddIfMissing(myObject);
ロジックをオブジェクトに移動することによってのみ、両方の操作をロックで囲み、安全にすることができます。
これ以上の詳細がなければ、さらにコメントするのは難しいですが、次のことをお勧めします。
説明する:
public class Person {
public string FullName { get; private set; }
public string FamilyName { get; private set; }
public string KnownAs { get; private set; }
public void SetNames( string full, string family, string known) {
lock (padLock) {
...
}
}
}