一意のキー、つまり 1(a,b) 2(c,d) などに対して複数の値を追跡する必要があります...
ソリューションは複数のスレッドによってアクセスされるため、効果的に次のように定義しています。
ConcurrentSkipListMap<key, ConcurrentSkipListSet<values>>
私の質問は、値セットのサイズが 0 の場合のキーの削除を同期する必要があるかどうかです。2 つのクラスが「同時」であることはわかっており、OpenJDK ソース コードを確認しましたが、Set が空であることを確認し、remove(...) で Map を削除する 1 つのスレッド T1 の間にウィンドウがあるように見えます。別のスレッド T2 が add(...) を呼び出しています。その結果、T1 は最後の Set エントリを削除し、Set エントリを追加するだけで T2 とインターリーブされた Map を削除します。したがって、マップと T2 セットのエントリは T1 によって削除され、データは失われます。
add() メソッドと remove() メソッドを「同期」するだけですか、それとも「より良い」方法がありますか?
Map は複数のスレッドによって変更されますが、2 つの方法でのみ変更されます。
コード スニペットは次のとおりです。
protected static class EndpointSet extends U4ConcurrentSkipListSet<U4Endpoint> {
private static final long serialVersionUID = 1L;
public EndpointSet() {
super();
}
}
protected static class IDToEndpoint extends U4ConcurrentSkipListMap<String, EndpointSet> {
private static final long serialVersionUID = 1L;
protected Boolean add(String id, U4Endpoint endpoint) {
EndpointSet endpoints = get(id);
if (endpoints == null) {
endpoints = new EndpointSet();
put(id, endpoints);
}
endpoints.add(endpoint);
return true;
}
protected Boolean remove(String id, U4Endpoint endpoint) {
EndpointSet endpoints = get(id);
if (endpoints == null) {
return false;
} else {
endpoints.remove(endpoint);
if (endpoints.size() == 0) {
remove(id);
}
return true;
}
}
}