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

时间:2014-10-22 06:33:35

标签: java multithreading thread-safety

在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模块。

2 个答案:

答案 0 :(得分:2)

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

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

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

(另一方面,这些"皮带和牙套"预防措施是无害的,性能影响微不足道:可能无法测量。)


对于记录,类初始化的过程在Section 12.4.2中的JLS中指定。

答案 1 :(得分:0)

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

从我在Jetty WebAppContext中看到的内容中,只能在配置中设置一个类加载器。