为什么静态最终变量使用静态方法初始化需要同步



在Jetty源代码中,jetty-xml模块XmlConfiguration具有以下代码:

java private static final XmlParser __parser = initParser();
private synchronized static XmlParser initParser() {
XmlParser parser = new XmlParser();
URL config60 = Loader.getResource(XmlConfiguration.class, "org/eclipse/jetty/xml/configure_6_0.dtd");
URL config76 = Loader.getResource(XmlConfiguration.class, "org/eclipse/jetty/xml/configure_7_6.dtd");
URL config90 = Loader.getResource(XmlConfiguration.class, "org/eclipse/jetty/xml/configure_9_0.dtd");
parser.redirectEntity("configure.dtd", config90);
parser.redirectEntity("configure_1_0.dtd", config60);
parser.redirectEntity("configure_1_1.dtd", config60);
...
return parser;

__parser变量使用静态方法initParser()初始化。__parser应该是线程安全的,只能由类加载器加载一次,为什么initParser()需要使用synchronized?是否过量?

进一步解释:我从jetty-start模块调试Jetty源代码,然后调用jetty-xml模块。

我认为它根本不需要同步。

Java语言规范保证Java类初始化(即类statics的初始化等)在锁内执行,以防止竞争条件。这适用于类加载一次还是多次(即由不同的类加载程序)。

我怀疑这段代码的作者根本不知道JVM是如何处理的,并且采取了不必要的预防措施。

(另一方面,这些"安全带和背带"预防措施是无害的,对性能的影响很小:可能无法测量。)


为了记录,类初始化程序在第12.4.2节的JLS中规定。

如果您确保最多有一个类加载器,那么就不需要同步。每个类加载器运行一次静态初始化代码。

从JettyWebAppContext中可以看到,在配置中只能设置一个类加载器。

最新更新