private final ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();
private List<ReferenceCountExchangeClient> getSharedClient(URL url, int connectNum) {
String key = url.getAddress();
// 略去无关代码
// 【1】
locks.putIfAbsent(key, new Object());
// 【2】
synchronized (locks.get(key)) {
clients = referenceClientMap.get(key);
if (checkClientCanUse(clients)) {
batchClientRefIncr(clients);
return clients;
}
connectNum = Math.max(connectNum, 1);
if (CollectionUtils.isEmpty(clients)) {
clients = buildReferenceCountExchangeClientList(url, connectNum);
referenceClientMap.put(key, clients);
} else {
for (int i = 0; i < clients.size(); i++) {
ReferenceCountExchangeClient referenceCountExchangeClient = clients.get(i);
if (referenceCountExchangeClient == null || referenceCountExchangeClient.isClosed()) {
clients.set(i, buildReferenceCountExchangeClient(url));
continue;
}
referenceCountExchangeClient.incrementAndGetCount();
}
}
// 【3】
locks.remove(key);
return clients;
}
}
Environment
Steps to reproduce this issue
locks.remove(key)真正 remove 之前,线程 B 刚好执行到locks.putIfAbsent(key, new Object())。locks.get(key)之前,正好 A remove 完成。locks.get(key)将拿到 null,此时 抛出 NPE