intern'd字符串如何在不同的线程和classloarders之间表现?

时间:2012-02-15 13:15:48

标签: java string locking thread-safety classloader

在java的文档中,它表示在下面的例子中,条件为真:

String a = new String("ABC");
String b = new String("ABC");

if (a.intern() == b.intern())
{
 ....
}

我想知道,如果在考虑ab在不同的Threads或甚至不同的ClassLoaders中定义时仍然如此?

当我需要能够根据实体的名称同步加载某个配置的块时,这个问题就出现了,所以我想做类似的事情:

synchronized (entityName.intern())
{
}

我不确定这是一个好习惯,所以我可能不会追求这个方向 - 但这个问题仍然让我感兴趣。

2 个答案:

答案 0 :(得分:3)

如果在不同的线程上,是的,条件将为真。

如果在不同的类加载器上,我不会指望条件为真。 (但是你真的使用不同的类加载器加载了String的两个副本吗?)文档说明internString内使用自己的缓存实现。来自String#intern documentation

  

返回字符串对象的规范表示。

     

字符串池(最初为空)由班级String私下维护。

(我的重点)

所以,如果你以某种方式使用不同的类加载器两次加载String类(我不知道你会怎么做,但我打赌有一种方法),那么两个String类会每个都有自己的缓存 - 在理论。但是,实施可能不会那么好。 intern是Oracle JVM中的本机方法,使用在C ++中实现的符号表。我没有密切关注逻辑,看看在你讨论的边缘情况下,同一个JVM中的String的两个实例是否会共享相同的符号表。但在那时,我们正在考虑实施,这可能会有所不同。 文档建议不,它们不是相同的字符串。

答案 1 :(得分:0)

是的 - 实习在整个JVM中都有效。

如果您通过不同的类加载器加载多个版本的java.lang.String,我会非常关注您的执行环境......实习将是您最不担心的问题。