我试图确定MDC
使用 Cacheable ThreadPools 或 Spring 的 Async 注释时的线程安全性如何。
我有一个调用多个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);
}
}
由于 ThreadPools 重用了已经产生的线程,并且 MDC 使用 ThreadLocal 上下文映射。我们是否有可能丢失或损坏存储在 MDC 中的值?如果是这样,可能发生这种情况的潜在情况是什么?