2014-09-30 27 views
0

我有一段代码,我试图从中获取我的类的实例,因为我已经编写了一个围绕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); 

现在当我运行我的静态分析工具时,它正在抱怨 -

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) { 
    final ClientLogger result; 

    result = new ClientLogger(klass); 
    s_classLoggers.putIfAbsent(klass, result); 

    return 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)); 
    if (result == null) { 
     result = new ClientLogger(klass); 
    }  

    return result; 
} 

回答

2

您的代码不是线程安全的,因为不同的线程可能会在第一个线程上的两个调用之间调用put()

而应该拨打putIfAbsent()

+0

由于java 8或将字段的声明类型更改为'ConcurrentHashMap'。 – 2014-09-30 00:45:40

+0

我看不到's_classLoggers'地图的'putIfAbsent()'。不知道为什么?我正在使用'java.util.concurrent.ConcurrentHashMap' – john 2014-09-30 00:47:23

+0

@ user2809564:您需要将该字段的类型更改为'ConcurrentHashMap '。 – SLaks 2014-09-30 00:48:42

1

你的代码的一个在线测试

s_classLoggers.containsKey(klass) 

。几行后面你输入一个值

s_classLoggers.put(klass, result); 

当然,另一个线程可能同时更新了哈希映射。在多线程中,您不能在一行上进行测试,然后有条件地在另一行上进行操作,因为条件可能是错误的。以同样的方式,get之后的一行可能会返回null,因为另一个线程可能已经删除了之前有一行的条目。

原子操作,其中测试和更新在一个单一的操作完成:

newLogger = new ClientLogger(klass); 
result = s_classLoggers.putIfAbsent(klass, newLogger); 
if (result == null) { 
    result = newLogger; 
} 

(改变上面的代码,这样的结果是永远的任何值被映射,因为的putIfAbsent,如果没有被映射返回null之前,在这种情况下,newLogger将被放入地图中。)

+0

我没有看到's_classLoggers'映射的'putIfAbsent()'。不知道为什么?我正在使用'java.util.concurrent.ConcurrentHashMap' – john 2014-09-30 00:48:45

+0

这里是文档链接: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#putIfAbsent %28K,%20V%29 – AgilePro 2014-09-30 00:51:39

+0

'result = s_classLoggers.putIfAbsent(klass,new ClientLogger(klass));'这将在第一次调用时返回null。对?然后在我的代码中抛出NPE异常。 – john 2014-09-30 01:45:02

相关问题