是否有任何书面证明String.intern()的线程安全保证?javadoc暗示了它,但没有直接解决它:
String.intern()
返回字符串对象的规范表示。最初为空的字符串池由String类私有维护。 调用intern方法时,如果池已经包含等于equals(Object)方法确定的此String对象的字符串,则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。 因此,对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.intern()== t.intern()才为true。 所有文字字符串和字符串值常量表达式都将被插入。字符串文字在Java™语言规范的第3.10.5节中定义。
返回字符串对象的规范表示。最初为空的字符串池由String类私有维护。
调用intern方法时,如果池已经包含等于equals(Object)方法确定的此String对象的字符串,则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。
因此,对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.intern()== t.intern()才为true。
所有文字字符串和字符串值常量表达式都将被插入。字符串文字在Java™语言规范的第3.10.5节中定义。
值得注意的是,javadoc表示可以保证返回池中的字符串,但不能保证池本身是线程安全的(因此,在编写时,它似乎为争用线程而替换池条目打开了大门。 ,尽管我认为这种解释不太可能)。
和的JDK源String节目intern()是不揭示它的线程安全的灯光一个本地方法:
String
intern()
public native String intern();
我关心的是具体涉及到是否以下将全部线程安全的,保证只有一个MyObject是 创建 (不只是存储在缓存中)在并发请求面对每个唯一的字符串值:
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()是线程安全的,并且上面的代码还不错,但是缺乏可靠的消息来源的直接确认使我有些担心。
实际上,这听起来像您可能需要Guava Striped<Lock>,它以散列方式将对象映射到锁。如果您正在使用的任何其他代码具有相同的想法,则对内联字符串进行同步似乎是一个潜在的危险黑客,它可能会产生怪异的副作用。
Striped<Lock>