ユーザーがマルチスレッド コンテキストでクラスの非スレッド セーフ メソッドを使用しようとしたときに例外をスローする方法はありますか? 問題は主に、複数のスレッドがメソッドを使用しようとしていることを検出することだと思います。または、関数宣言で使用できる「not_synchronous」キーワード/タグはありますか?
4 に答える
スレッドがメソッドを実行できるようにする前に、そのメソッドが既に使用されているかどうかを確認できますが、それはロックを使用する場合と大差ありません (注: 私の例は再入可能ではありません)。
private static final AtomicBoolean used = new AtomicBoolean();
public static void unsafe() throws InterruptedException {
if(!used.compareAndSet(false, true)) {
throw new IllegalStateException();
}
//do you stuff
used.set(false);
}
これを行う簡単な方法はありません。複数のスレッドがメソッドを使用していることを検出した場合は、スレッドセーフなコレクションなどを使用する必要がある可能性があります。それをすべて行っている場合は、メソッド自体をスレッドセーフにする必要があります。
グレイの答えを拡張するには、これを実行したいとします (メソッドが複数のスレッドで使用されていることを検出します)。これの単純な (そして正しくない) 実装は次のようになります。
volatile boolean methodBeingUsed = false;
public void doSomething() {
if (methodBeingUsed) throw new IllegalStateException("You can't do that!");
try {
methodBeingUsed = true;
// do something...
} finally {
methodBeingUsed = false;
}
}
わかりました...しかし、2 つのスレッドが両方とも最初のif (methodBeingUsed)
チェックを通過し、同時にクリティカル セクションに入る可能性があります。それでは、methodBeingUsed
フラグを保護するためにロックを追加してみましょう。
Lock methodLock = new ReentrantLock();
volatile boolean methodBeingUsed = false;
public void doSomething() {
try {
lock.lock();
if (methodBeingUsed) throw new IllegalStateException("You can't do that!");
methodBeingUsed = true;
} finally {
lock.unlock();
}
try {
// do something...
} finally {
try {
lock.lock();
methodBeingUsed = false;
} finally {
lock.unlock();
}
}
}
もちろん、これは doSomething() が自分自身を再帰的に呼び出すことができないことを前提としています。可能であれば、呼び出し元のスレッドも追跡する必要があります。私が今考えていない他の条件を説明するために、いくつかのチェックを追加してください。複数のスレッドによって使用されているメソッドを検出するためにロジックを同期するために費やされた労力は、メソッドスレッドを作成するだけに費やされたほうがよいことが簡単にわかります。 - 最初から安全です。
実際、あなたの目標が「複数のスレッドがこのメソッドを使用しようとしている」ことを判断することであり、それを「複数のメソッド...同時に」に制限していない場合-(許してください)アレックスのコードを適応させることができますうまく:
に変更
methodBeingUsed
しthreadOwningMethod
、 の代わりにスレッドに設定しますtrue
。最後にクリアする必要はありません。ロック/ロック解除の手順を保存してください。所有されると、所有されます(資本主義の豚!!)。
threadOwningMethod
ロックを発生させることなく、現在のスレッドと一致するか (A-OK)、一致しないか (例外をスロー) を事前にチェックできます。設定されていない (null) 場合は、1 回限りのヒットが発生します: check/lock/check&set/unlock;threadOwningMethod
揮発性とマークされているため、これは安全です。