Java 静态分析期间非原子性地使用检查/输入错误
我有一段代码,我试图从中获取类的实例,因为我编写了一个关于Java 静态分析期间非原子性地使用检查/输入错误,java,multithreading,atomic,Java,Multithreading,Atomic,我有一段代码,我试图从中获取类的实例,因为我编写了一个关于java.util.logging.Logger的包装器 下面是我的ClientLogger类中的代码片段- private static final Map<Class<?>, ClientLogger> s_classLoggers = new ConcurrentHashMap<Class<?>, ClientLogger>(); final private Logger m_log
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;
}
现在,当我运行静态分析工具时,它正在抱怨-
Non-atomic use of check/put on this line s_classLoggers.put(klass, result);
在我的ClientLogger
课程中,我不知道为什么?我在这里做错什么了吗
更新:-
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));
if (result == null) {
result = new ClientLogger(klass);
}
return result;
}
这是我的最新代码-
private static final ConcurrentHashMap<Class<?>, ClientLogger> s_classLoggers = new ConcurrentHashMap<Class<?>, ClientLogger>();
public static ClientLogger getInstance(final Class<?> klass) {
final ClientLogger result;
result = new ClientLogger(klass);
s_classLoggers.putIfAbsent(klass, result);
return result;
}
私有静态最终ConcurrentHashMap,ClientLogger>();
公共静态ClientLogger getInstance(最终类klass){
最终客户记录结果;
结果=新客户端记录器(klass);
s_类记录器。putIfAbsent(klass,结果);
返回结果;
}
另一个更新:-
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));
if (result == null) {
result = new ClientLogger(klass);
}
return result;
}
私有静态最终ConcurrentHashMap,ClientLogger>();
公共静态ClientLogger getInstance(最终类klass){
客户记录结果;
结果=s_classLoggers.putIfAbsent(klass,新客户端记录器(klass));
如果(结果==null){
结果=新客户端记录器(klass);
}
返回结果;
}
您的代码不是线程安全的,因为不同的线程可能会在第一个线程的两次调用之间调用put()
相反,您应该调用
putIfAbsent()
您的代码不是线程安全的,因为不同的线程可能会在第一个线程的两次调用之间调用put()
相反,您应该调用
putIfAbsent()
您的代码不是线程安全的,因为不同的线程可能会在第一个线程的两次调用之间调用put()
相反,您应该调用
putIfAbsent()
您的代码不是线程安全的,因为不同的线程可能会在第一个线程的两次调用之间调用put()
相反,您应该调用正在测试的putIfAbsent()
s_classLoggers.containsKey(klass)
在代码的一行上。几行之后,您输入了一个值
s_classLoggers.put(klass, result);
当然,另一个线程可能同时更新了哈希映射。在多线程处理中,不能在一行上测试,然后在另一行上有条件地操作,因为条件可能是false。同样,稍后的get
a行可能会返回null,因为另一个线程可能已经删除了前一行中的条目
原子操作,其中测试和更新在单个操作中完成:
newLogger = new ClientLogger(klass);
result = s_classLoggers.putIfAbsent(klass, newLogger);
if (result == null) {
result = newLogger;
}
(更改了上面的代码,使结果始终是映射的任何值,因为如果之前未映射任何内容,则putIfAbsent将返回null,在这种情况下,新记录器将放入映射中。)您正在测试
s_classLoggers.containsKey(klass)
在代码的一行上。几行之后,您输入了一个值
s_classLoggers.put(klass, result);
当然,另一个线程可能同时更新了哈希映射。在多线程处理中,不能在一行上测试,然后在另一行上有条件地操作,因为条件可能是false。同样,稍后的get
a行可能会返回null,因为另一个线程可能已经删除了前一行中的条目
原子操作,其中测试和更新在单个操作中完成:
newLogger = new ClientLogger(klass);
result = s_classLoggers.putIfAbsent(klass, newLogger);
if (result == null) {
result = newLogger;
}
(更改了上面的代码,使结果始终是映射的任何值,因为如果之前未映射任何内容,则putIfAbsent将返回null,在这种情况下,新记录器将放入映射中。)您正在测试
s_classLoggers.containsKey(klass)
在代码的一行上。几行之后,您输入了一个值
s_classLoggers.put(klass, result);
当然,另一个线程可能同时更新了哈希映射。在多线程处理中,不能在一行上测试,然后在另一行上有条件地操作,因为条件可能是false。同样,稍后的get
a行可能会返回null,因为另一个线程可能已经删除了前一行中的条目
原子操作,其中测试和更新在单个操作中完成:
newLogger = new ClientLogger(klass);
result = s_classLoggers.putIfAbsent(klass, newLogger);
if (result == null) {
result = newLogger;
}
(更改了上面的代码,使结果始终是映射的任何值,因为如果之前未映射任何内容,则putIfAbsent将返回null,在这种情况下,新记录器将放入映射中。)您正在测试
s_classLoggers.containsKey(klass)
在代码的一行上。几行之后,您输入了一个值
s_classLoggers.put(klass, result);
当然,另一个线程可能同时更新了哈希映射。在多线程处理中,不能在一行上测试,然后在另一行上有条件地操作,因为条件可能是false。同样,稍后的get
a行可能会返回null,因为另一个线程可能已经删除了前一行中的条目
原子操作,其中测试和更新在单个操作中完成:
newLogger = new ClientLogger(klass);
result = s_classLoggers.putIfAbsent(klass, newLogger);
if (result == null) {
result = newLogger;
}
(更改了上面的代码,使结果始终是映射的任何值,因为如果之前未映射任何内容,则putIfAbsent将返回null,在这种情况下,将newLogger放入映射中。)从java 8开始,或者将声明的字段类型更改为ConcurrentHashMap
。我看不到putIfAbsent()
用于s\u类记录器
map。不知道为什么?我正在使用java.util.concurrent.ConcurrentHashMap
@user2809564:您需要将字段的类型更改为ConcurrentHashMap
@SLaks,我不明白。你能修改一下你的答案吗?这样我就能明白你的意思了?你的意思是说泛型?@user2809564你的s_classLoggers
字段的类型是Map
。将其更改为ConcurrentHashMap
类型。从java 8开始,或者将声明的字段类型更改为ConcurrentHashMap
。对于s_类记录器
映射,我看不到putIfAbsent()
。不知道为什么?我正在使用java.util.concurrent.ConcurrentHashMap
@user2809564:您需要将字段的类型更改为ConcurrentHashMap
@SLaks,我不明白。你能修改一下你的答案吗?这样我就能知道你的意思了