私のプロパティへのアクセスを同期させるために、ReaderWriterLockSlimクラスを使用します。スレッドセーフな方法でプロパティにアクセスするには、次のコードを使用します。ReaderWriterLockSlim.IsReadLockHeld/IsWriteLockHeldに対するマイクロソフトの発言とその結果
public class SomeClass
{
public readonly ReaderWriterLockSlim SyncObj = new ReaderWriterLockSlim();
public string AProperty
{
get
{
if (SyncObj.IsReadLockHeld)
return ComplexGetterMethod();
SyncObj.EnterReadLock();
try
{
return ComplexGetterMethod();
}
finally
{
SyncObj.ExitReadLock();
}
}
set
{
if (SyncObj.IsWriteLockHeld)
ComplexSetterMethod(value);
else
{
SyncObj.EnterWriteLock();
ComplexSetterMethod(value);
SyncObj.ExitWriteLock();
}
}
}
// more properties here ...
private string ComplexGetterMethod()
{
// This method is not thread-safe and reads
// multiple values, calculates stuff, ect.
}
private void ComplexSetterMethod(string newValue)
{
// This method is not thread-safe and reads
// and writes multiple values.
}
}
// =====================================
public static SomeClass AClass = new SomeClass();
public void SomeMultiThreadFunction()
{
...
// access with locking from within the setter
AClass.AProperty = "new value";
...
// locking from outside of the class to increase performance
AClass.SyncObj.EnterWriteLock();
AClass.AProperty = "new value 2";
AClass.AnotherProperty = "...";
...
AClass.SyncObj.ExitWriteLock();
...
}
私が手やかつて私はReaderWriterLockSlim
-objectを発表し、クラスの外から、私はプロパティの束を取得または設定しようと思いたびにそれをロックする複数のプロパティを設定するたびに、不要なロックを回避するために。これを実現するには、getterメソッドとsetterメソッドを使用して、IsReadLockHeld
プロパティとIsWriteLockHeld
プロパティを使用してロックが取得されているかどうかを確認してください(ReaderWriterLockSlim
)。これは正常に動作し、私のコードのパフォーマンスが向上しました。
これまでのところは良いが、私は時期についてIsReadLockHeld
とIsWriteLockHeld
ドキュメントを再読み込み、私は発言フォームマイクロソフトに気づい:
このプロパティは、アサートまたはその他のデバッグ の目的のために使用するためのものです。プログラムの実行フローを制御するために使用しないでください。
私の質問は:なぜ、この目的のためにIsReadLockHeld/IsWriteLockHeld
を使用してはならない理由はありますか?私のコードに何か問題はありますか?再帰的ロック(LockRecursionPolicy.SupportsRecursion
)を使用するよりも、すべてが期待どおりに動作します。
これを明確にする:これは最小の例です。私は、ロック自体が必要かどうか、あるいは別の方法で取り除くことができるかどうかを知りたくありません。私はちょうどなぜIsReadLockHeld
/IsWriteLockHeld
を使用して、ドキュメンテーションの記述通りにプログラムの流れを制御すべきではないかを知りたいと思っています。
ReaderWriteLockSlimは何も保護しません。.NETは既に、オブジェクト参照の更新がアトミックであることを約束しています。それが持つ唯一のマイルドな副作用は、セッターの更新が他のスレッドで見えるということです。 MemoryBarrier()を使用するほうがはるかに安いです。スレッドセーフの保証はありません.SyncObjは誤った安全感しか与えないので、SyncObjを完全に削除する方が良いでしょう。 –
@EricLippert:IsRead/WriteLockHeldのドキュメントは、現在のスレッド*がロックを保持しているときに 'true'を返すことを示唆しています。 'IsRead/WriteLockHeld'がtrueを返す場合、' ExitRead/WriteLock'への明示的な呼び出しなしに、そのスレッドでロック状態がどのように変更されますか? – Iridium
@イリジウム:私のコメントを撤回します。私は今、文書がその警告をなぜ出さないのか、実際は分かりません。つまり、ベストプラクティスはドキュメンテーションが言っていることをすることです。 –