記事ディレクトリ
public void synchronizedMethod(Integer id) {
synchronized (id) {
// Code to be synchronized
}
}
エラー分析
Synchronize on a new "Object" instead.
プリミティブ ラッパー (整数、long、ブール値など) はオートボックス化によって作成される可能性があり、Sonar はこれを危険であるとみなしているため、同期は行わないでください。synchronized ステートメントで使用されるロック オブジェクトは、同期されるすべてのスレッドにわたって一定である必要があるため、これは危険です。プログラム ロジックで再利用される可能性のある動的オブジェクトは、簡単に同期エラーを引き起こす可能性があります。したがって、ベスト プラクティスは、Object をインスタンス化し、同期のみに使用される特別なロック オブジェクトを作成することです。
まず、Sonar のソリューションを見てみましょう。
彼女が定数オブジェクトを要求していることがわかりますが、それは明らかに私が望んでいることではありません。私が望んでいるのは、異なる ID の入力が非同期であり、同じ ID のみがロックされることです。
最終的解決
ID をロックとして使用するには、Java でカスタム クラスを作成して ID を保存し、それをモニターとして同期します。以下に例を示します。
import java.util.HashMap;
import java.util.Map;
public class SynchronizationExample {
private Map<Integer, Object> locks = new ConcurrentHashMap<>();
public void synchronizedMethod(Integer id) {
synchronized (getLock(id)) {
// 需要同步的代码块
}
}
private Object getLock(Integer id) {
locks.putIfAbsent(id, new Object());
return locks.get(id);
}
}
この例では、 を使用して、HashMap
各 ID に関連付けられたロック オブジェクトを保存します。synchronizedMethod
このメソッドは ID パラメータを受け取り、locks
マップから取得した対応するロック オブジェクトを使用してコード ブロックを同期します。
getLock
HashMap
メソッドは、 のメソッドを使用して、ID ごとに一意のロック オブジェクトが確実に作成されるようにしますputIfAbsent
。指定された ID に対応するロック オブジェクトがマップ内にlocks
ない場合は、新しいロック オブジェクトが作成され、マップに保存されます。同じ ID の場合、後続の呼び出しでは、getLock
以前に作成されたロック オブジェクトが返されます。
ID をlocks
マップのキーとして使用すると、特定のロックを各 ID に関連付けることができ、すべての ID にわたるのではなく、各 ID の同期を確保できます。
カスタム オブジェクトをロックとして使用する場合は、潜在的な同時実行性の問題を回避するために、基になるデータ構造にアクセスして変更するときにスレッドの安全性を確保してください。