gpt4 book ai didi

java - 如何删除检查/放置的非原子使用并使代码线程安全?

转载 作者:行者123 更新时间:2023-11-29 05:17:09 25 4
gpt4 key购买 nike

我有一个代码,我试图从中获取我的类的实例,因为我已经围绕 java.util.logging.Logger 编写了一个包装器。

下面是我的 ClientLogger 类中的代码片段 -

private static final Map<Class<?>, ClientLogger> s_classLoggers = new ConcurrentHashMap<Class<?>, ClientLogger>();

final private Logger m_logger;

private ClientLogger(final Class<?> caller) {
m_logger = Logger.getInstance(caller);
}

public static ClientLogger getInstance(final Class<?> klass) {
final ClientLogger result;

if (s_classLoggers.containsKey(klass)) {
result = s_classLoggers.get(klass);
} else {
result = new ClientLogger(klass);
s_classLoggers.put(klass, result);
}

return result;
}

这就是我在需要使用上述记录器的其他类中初始化它的方式 -

private static final ClientLogger s_logger = ClientLogger.getInstance(TestLogger.class);

现在当我运行我的静态分析工具时,它在我的 ClientLogger 类中提示 -

Non-atomic use of check/put on this line s_classLoggers.put(klass, result);

所以我像这样修改了上面的代码以使其线程安全 -

private static final ConcurrentHashMap<Class<?>, ClientLogger> s_classLoggers = new ConcurrentHashMap<Class<?>, ClientLogger>();

public static ClientLogger getInstance(final Class<?> klass) {
ClientLogger result;

result = s_classLoggers.putIfAbsent(klass, new ClientLogger(klass));
// is below line thread safe and efficient?
if (result == null) {
result = new ClientLogger(klass);
}

return result;
}

下面是我将初始化它以获取我的记录器实例的方式 -

private static final ClientLogger s_logger = ClientLogger.getInstance(TestLogger.class);

那么我上面的代码线程安全吗?我正在做 result == null 检查,因为这是第一次,它不会出现在 map 中,所以我需要为它创建一个新值,因此,我需要删除结果的最终修饰符。

最佳答案

你需要的是 Java 8 的

s_classLoggers.computeIfAbsent(klass, ClientLogger::new);

这只会在确实需要时创建对象。

请注意,ClientLogger::new 是惊人的缩写形式,因为它是 k -> new ClientLogger(k) 的缩写,它是

的缩写
new Function<Class<?>, ClientLogger>() {
public ClientLogger apply(Class<?> k) {
return new ClientLogger(k);
}
}

lambda 甚至不会在编译时生成类,尽管 JVM 可以(并且在 Java 8 中确实如此)在运行时创建类。

否则您可能会发现使用写锁更安全。

public static ClientLogger getInstance(final Class<?> klass) {
ClientLogger result = s_classLoggers.get(klass);
if (result != null)
return result; // fast path

// slow, but rare path
synchronized (s_classLoggers) {
result = s_classLoggers.get(klass);
if (result == null)
s_classLoggers.put(klass, result = new ClientLogger(klass));
}
return result;
}

关于java - 如何删除检查/放置的非原子使用并使代码线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26125723/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com