Javaマルチスレッドの問題があります。2つのスレッドがmethodA()にアクセスしており、その中にはforループがあり、ループ内ではmethodB()が呼び出されます。メソッドAはスレッド名ロックを使用してロックする必要があり、メソッドBはメソッドBが操作するオブジェクトIDでロックする必要があります。以下のコードを確認してください。
現在のコード
private static final ConcurrentHashMap<Object, Object> LOCKS = new ConcurrentHashMap<Object, Object>();
private void methodA(){
LOCKS.putIfAbsent(Thread.currentThread().getName(), new Object()))
synchronized (LOCKS.putIfAbsent(Thread.currentThread().getName(), new Object())) {
for(loop through all objects) {
methodB(Object1);
}
}
}
private void methodB(Object1 object1) {
LOCKS.putIfAbsent(object1.getObjectId(), new Object()))
synchronized(LOCKS.putIfAbsent(object1.getObjectId(), new Object())){
//<Work on object1>
}
}
2つの異なるスレッドがmethodA()に並列アクセスできるようにするために上記のコードを実行しましたが、methodB()(methodA()によって呼び出される)で一度に同じObject1で動作しないようにする必要があります。すなわち; スレッドAとスレッドBが同時にmethodA()にアクセスするようにしたいのですが、これは'for'ループ内のすべてのオブジェクトをループし、methodB()を呼び出すことによってそれぞれを操作しますが、スレッドAとBは一度に同じオブジェクトインスタンスに作用します。したがって、オブジェクトインスタンスIDに基づいてmethodB()をロックする上記のコード。
改善が必要です。
上記のコードで、スレッドAとスレッドBがmethodB()に到達し、両方が同じオブジェクト'obj1'で動作することを検出した場合、上記のコードでは、スレッドAが待機するか、スレッドBがもう一方を待機します。最初にmethodB()に到達してロックした人に応じて1つ終了します。
しかし、スレッドAが最初にロックを取得してmethodB()を実行すると、「obj1」の処理が完了するまでに9時間かかる場合を想像してみてください。この場合のスレッドBは、methodB()を実行して「obj1」を処理する機会を得る前に、9時間全体を待機する必要があります。
私はこれが起こらないようにしたい。スレッドBは、methodB()が'obj1'の名前でロックされていることを検出すると、スレッドAは他のオブジェクトのロックと処理を試みるために先に進む(そして後でobj1に戻る)必要があります。すなわち; オブジェクトのリストにあるobj1、obj2などの'for'ループ内の他のオブジェクトの処理を試みる必要があります。
この「待機なしのロック」問題を解決するための入力はありがたいです。
助けてくれてありがとう。
答えを改善するためのいくつかの説明。
- methodA()とmethodB()の両方が同じクラスにあります。methodB()はObjectクラスにありません。
- 実際、スレッドAとスレッドBは、AとBを含む多くのメソッドを呼び出すタイマースレッドです。したがって、スレッドレベルのロック(スレッドは15分ごとに呼び出され、methodA()の最初の実行が前に完了しない可能性があるため)それへの2回目の呼び出し)。
- methodB(Obj1)は常にObject1パラメータを取り、それにロックする必要があります。その理由は、このクラスには、Object1パラメーターも取り込むmethodC(Obj1)やmethodD(Obj1)などの他のメソッドがあるためです。これらのメソッドは、Object1の同じインスタンスに対して同時に実行されるべきではありません。したがって、Object1パラメータのロックが必要です。
- methodB(Obj1 obj)がobj1のスレッドA()によってすでにロックされていることを検出したスレッドBは、別のオブジェクト、たとえばobj2を使用してmethodB()を再度呼び出す必要があります。他の人と一緒に終了すると、obj1に戻るはずです。