String.intern()线程安全保证?

时间:2014-02-19 19:14:47

标签: java string multithreading

是否有任何文件证明String.intern()是线程安全的? javadoc暗示它但不直接解决它:

  

返回字符串对象的规范表示。一池水   最初为空的字符串由String类私有维护。

     

当调用实习方法时,如果池已包含   字符串等于此字符串对象由equals(Object)确定   方法,然后返回池中的字符串。否则,这个   String对象被添加到池中以及对此String的引用   返回对象。

     

对于任何两个字符串s和t,s.intern()== t.intern()   当且仅当s.equals(t)为真时才为真。

     

所有文字字符串和字符串值常量表达式都是   实习。字符串文字在The的3.10.5节中定义   Java™语言规范。

值得注意的是,javadoc说保证池中的String被返回,但不是池本身是线程安全的(因此写入它似乎会打开门,以便在事件中替换池条目竞争线程,虽然我认为这种解释不太可能。)

String的JDK源代码显示intern()是一个本机方法,它没有阐明其线程安全性:

public native String intern();

我的担忧与以下是否完全线程安全有关,保证只有一个MyObject 创建(不仅仅存储在缓存中),用于每个唯一的字符串值。面对并发请求:

public void myMethod(String myString)
{
    // Get object from cache, the cache itself is thread safe
    MyObject object = myCache.get(myString);
    if (object == null)
    {
        synchronized(myString.intern())
        {
            // Retry cache to avoid race condition
            object = myCache.get(myString);
            if (object == null)
            {
                object = new MyObject(myString);
                // ... do some startup / config of the object ...
                myCache.put(object);
            }
        }
    }
    // do something useful with the object
}

我希望避免在方法或缓存本身上进行同步,因为对象的创建可能需要一些时间(需要网络访问)。有一些解决方法,例如维护本地线程安全缓存/字符串池,但除非必要,否则不值得做。 String.intern()(无法从缓存中删除被拦截的字符串)的内存含义与此特定用例无关(使用少量字符串)。

我相信String.intern()是线程安全的,并且上面的代码很好,但缺乏来自信誉良好的来源的直接确认让我有点担心。

以前曾多次询问过这个问题,但没有提供具体参考答案:

1 个答案:

答案 0 :(得分:4)

实际上听起来你可能想要一个Guava Striped<Lock>,它以散列的方式将对象映射到锁。如果您正在使用的任何其他代码具有相同的想法,那么在实习字符串上进行同步似乎是一个可能具有weird side effects的潜在危险黑客。