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,我不明白。你能修改一下你的答案吗?这样我就能知道你的意思了