Is there any documented guarantee that String.intern()
is thread safe? The javadoc alludes to it but does not address it directly:
Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.
Notably, the javadoc says that a String from the pool is guaranteed to be returned, but not that the pool itself is thread safe (so as written it appears to leave the door open for a pool entry to be replaced in the event of competing threads, although I think this interpretation is unlikely).
And the JDK source of String
shows intern()
to be a native method which does not shed any light on its thread safety:
public native String intern();
My concern is specifically related to whether the following would be fully thread safe, guaranteeing only one MyObject
is created (not merely stored in the cache) for each unique string value in the face of concurrent requests:
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
}
I wish to avoid synchronizing on either the method or the cache itself since the creation of the object can take some time (entails network access). There are workarounds such as maintaining a local thread safe cache / pool of strings but it is not worth doing unless necessary. The memory implications of String.intern()
(inability to remove interned strings from the cache) are not relevant for this particular use case (small number of strings being used).
I believe that String.intern()
is thread safe and that the code above is fine, but the lack of direct confirmation from a reputable source leaves me slightly concerned.
This question has been asked here multiple times before, but no concrete answer with references has been provided:
The short answer to your question is yes. It's thread-safe.
1) Immutable objects are by default thread-safe because their state can not be modified once created. Since String is immutable in Java, it's inherently thread-safe. 2) Read-only or final variables in Java are also thread-safe in Java. 3) Locking is one way of achieving thread-safety in Java.
The distinct values are stored in a string intern pool. The single copy of each string is called its intern and is typically looked up by a method of the string class, for example String. intern() in Java. All compile-time constant strings in Java are automatically interned using this method.
String Interning is a method of storing only one copy of each distinct String Value, which must be immutable. By applying String. intern() on a couple of strings will ensure that all strings having the same contents share the same memory.
That actually sounds like you might want a Guava Striped<Lock>
, which maps objects to locks in a hashed way. Synchronizing on interned strings seems like a potentially dangerous hack that could have weird side effects if any other code you're using had the same idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With