OPは指定しませんでしたが、彼のシーンに複数のクライアント呼び出し間でオブジェクトをロックしておく必要がある可能性が含まれている場合(たとえば、クライアントから関数Aを呼び出す必要があり、結果に応じて関数BまたはCを呼び出します。オブジェクトを常に他のスレッドにロックしたままにする)、少し異なる方法で実装する必要があります。例:
public static class ThreadSafeThing {
private static UnsafeThing _thing = new UnsafeThing();
private static readonly object _lock = new object();
public static void getLock() {
Monitor.Enter(_lock);
}
public static void releaseLock() {
Monitor.Exit(_lock);
}
// this is your thread-safe version of Thing.DoSomething
public static bool DoSomething() {
try {
Monitor.Enter(_lock);
return _thing.DoSomething();
}
finally {
Monitor.Exit(_lock);
}
}
// this is your thread-safe version of Thing.DoSomethingElse
public static void DoSomethingElse() {
try {
Monitor.Enter(_lock);
return _thing.DoSomethingElse();
}
finally {
Monitor.Exit(_lock);
}
}
}
クライアントからの呼び出しから...
try {
ThreadSafeThing.getLock();
if (ThreadSafeThing.DoSomething()) {
ThreadSafeThing.DoSomethingElse();
}
}
finally {
// This must be called no matter what happens
ThreadSafeThing.releaseLock();
}
ここでの主な違いは、クライアントがロックを取得し、ロックが終了したら解放する責任があることです。これにより、ロックを維持しながら、オブジェクト全体で複数の関数を呼び出すことができます。releaseLock を使用してロックが解放されるまで、他のすべてのスレッドは getLock 呼び出しでブロックされます。
編集: DoSomething および DoSomethingElse メソッドにロックの自動取得を追加し、最初に getLock メソッドを介してロックを取得せずにこれらのメソッドを直接呼び出すと、スレッドが使い捨てロックも取得できるようにしました。ただし、この方法でロックを取得した場合、そのロックは 1 回のメソッド呼び出しの間しか持続しないことに注意してください。