众所周知,方法org.osgi.framework.Version.toString()
会导致性能问题(请参阅see Bug 324331 - redundant Strings created from Version.toString)。为了解决这个问题,方法已经改变,现在它利用数据竞争的懒惰初始化(可能是为了提高性能)
// OSGi Service Platform Release 4 Version 4.3 Core Companion Code
public String toString() {
if (versionString != null) {
return versionString;
}
int q = qualifier.length();
StringBuffer result = new StringBuffer(20 + q);
result.append(major);
result.append(SEPARATOR);
result.append(minor);
result.append(SEPARATOR);
result.append(micro);
if (q > 0) {
result.append(SEPARATOR);
result.append(qualifier);
}
return versionString = result.toString();
}
据我所知,这不是线程安全的,因为versionString
字段的读取可以重新排序,并且该方法可以返回null
值。我对吗?或者也许没关系,因为如果没有适当的同步,它永远不会被调用?
更新
据Jeremy Manson撰写的this博客文章,他是JLS并发第17章的作者之一,实际上可能会发生。
答案 0 :(得分:2)
这更多是关于缓存而不是懒惰。
但你是对的,根据Java Memory Model
它可以返回nullStringversionString;
public String toString() {
if (versionString != null) {
return versionString; // can return null here!!
}
理论上它可以转化为
String tmp1 = versionString; // reads null
String tmp2 = versionString; // reads non-null
if(tmp2!=null)
return tmp1; // return null!
然而,可能没有实际的JVM会这样做,所以这个bug可能永远不会实现。
然而,“正确”的事情是
public String toString() {
String tmp = versionString;
if (tmp != null) {
return tmp;
}
最后一行很好但是
return versionString = result.toString();
它不会读取versionString
,它等同于
String tmp3 = result.toString();
versionString = tmp3;
return tmp3;
有趣的是,即使我们做了
versionString = result.toString(); // [w]
return versionString; // [r]
它仍然是安全的。最后一次读取不能返回null,因为[w]发生在[r]之前。