这个问题由最开始使用JACKSON JSON而衍生出来因为官网上建议将ObjectMapper作为全局变量使用从而提高效率所以我们项目里面使用了单例在使用单例的时候我们无可厚非的考虑了资源在使用时是否要保证互斥的情况
最开始的写法
Java代码
public final class JacksonJsonMapper {
static volatile ObjectMapper objectMapper = null;
private JacksonJsonMapper(){}
public static ObjectMapper getInstance(){
if (objectMapper==null){
objectMapper = new ObjectMapper();
}
return objectMapper;
}
}
在此期间我考虑了两个问题并与团队中的另外一个兄弟发生了激烈的讨论
在使用getInstance()方法的时候是否要使用synchronized关键字
在使用objectMapperwriteValueAsString(object)时因为此方法非静态方法在此方法内是否会使用到对象自有的属性而在并发的时候出现前者属性被后者覆盖的问题
后再看了源码后排除了第二个顾虑ObjectMapper是与线程绑定的所以是线程安全的并且也在官网的线程安全介绍中得到了证实
Jackson follows threadsafety rules typical for modern factorybased Java data format handlers (similar to what say Stax or JAXP implementations do) For example:
Factories (ObjectMapper JsonFactory) are threadsafe once configured: so ensure that all configuration is done from a single thread and before instantiating anything with factory
Reader/writer instances (like JsonParser and JsonParser) are not threadsafe there is usually no need for them to be but if for some reason you need to access them from multiple threads external synchronization is needed
All transformer objects (custom serializers deserializers) are expected to be stateless and thereby thread safe state has to be stored somewhere outside instances (in ThreadLocal or context objects passed in like DeserializationContext)
第一个顾虑在看完下面这篇文章后得到了解决方法
l
Java代码
public final class JacksonJsonMapper {
static volatile ObjectMapper objectMapper = null;
private JacksonJsonMapper(){}
public static ObjectMapper getInstance(){
if (objectMapper==null){
synchronized (ObjectMapperclass) {
if (objectMapper==null){
objectMapper = new ObjectMapper();
}
}
}
return objectMapper;
}
}
文章中详细说明了关键字 volatile 是在读取所申明的对象时会要从内存中进行同步但是不会对写时起作用所以还是需要synchronized 关键字的配合