我想确定在使用可缓存的线程池或Spring Async注解时,MDC
的线程安全性如何。
我有一个调用多个CompletableFuture<>
并使用线程池执行它们的方法。
@Async
public CompletableFuture<List> someMethod(String request) {
try {
MDC.put("request", request)
MDC.put("loggable1", "loggable1");
MDC.put("loggable2", "loggable2");
log.info("Log Event");
} finally {
MDC.clear();
}
}
Logback的MDCAdapter相关部分
final ThreadLocal<Map<String, String>> copyOnThreadLocal = new ThreadLocal<Map<String, String>>();
public void put(String key, String val) throws IllegalArgumentException {
if (key == null) {
throw new IllegalArgumentException("key cannot be null");
}
Map<String, String> oldMap = copyOnThreadLocal.get();
Integer lastOp = getAndSetLastOperation(WRITE_OPERATION);
if (wasLastOpReadOrNull(lastOp) || oldMap == null) {
Map<String, String> newMap = duplicateAndInsertNewMap(oldMap);
newMap.put(key, val);
} else {
oldMap.put(key, val);
}
}
public void clear() {
lastOperation.set(WRITE_OPERATION);
copyOnThreadLocal.remove();
}
public void remove(String key) {
if (key == null) {
return;
}
Map<String, String> oldMap = copyOnThreadLocal.get();
if (oldMap == null)
return;
Integer lastOp = getAndSetLastOperation(WRITE_OPERATION);
if (wasLastOpReadOrNull(lastOp)) {
Map<String, String> newMap = duplicateAndInsertNewMap(oldMap);
newMap.remove(key);
} else {
oldMap.remove(key);
}
}
由于线程池重复使用已经创建的线程,并且MDC使用ThreadLocal上下文映射,因此我们是否可能会丢失或损坏存储在MDC中的值?如果是这样,可能发生这种情况的潜在场景是什么?