Garbage collector and String.intern ()
If i do
StringBuilder b = new StringBuilder();
b.append("foo").append("bar");
String s = b.toString().intern();
s = null;
Will the string "foobar"
generated by the StringBuilder
garbage collector be available ?
I doubt the method intern()
because I am syncing some code blocks of the application with the string id.
Something like that:
String id = getUserCurrentId() // this method generates IDs with StringBuider...
synchronized(id.intern()){
// .....
}
This is a desktop app with some threads and every logged in user owns the generated id in every login process.
source to share
I think this will work:
While even intern
ed Strings can be trashed (so you can get different instances of your user id over the lifetime of the JVM), they benefit if you are inside that synchronized block (because then String is still in use), so it should be stable enough for your purposes.
Even if you get another instance next time, it could mean that the lock didn't matter, so it doesn't matter.
But I didn't do it anyway.
How about using a ConcurrentHashMap to get named locks ?
source to share
When you call str.intern()
, you actually access the internal string instance, i.e. if this bite is already in the cache, you get a link to that instance.
When you speak:
String s = .... /* anything */
you create a variable that contains another reference to the same string. So when you say
s = null;
you just put null
in this link. This does not affect the object itself. Thus, it will be removed by the GC if the GC decides to remove it. You can still use the original object (the one that was written for the assignment operator) for synchronization. Of course it synchronized(id.intern())
looks fine. Although I have no idea why you want to do this.
Reusing BTW objects that are functional in your synchronization program is a very bad pattern. Think about the following scenario. You are using id.intern()
to sync. This means that if you are ID, for example foo
, and someone else in the program says
String s = 'foo'
it accesses the same object because string literals are cached. Now, if the following code is written in another part of the program:
String s = 'foo';
.....
synchronized(s) {
s.notify();
}
and in you it is written in your piece of code
synchronized(id.intern()) {
id.wait();
}
maybe yours wait()
will come out! This unexpected behavior is very difficult to debug. Therefore, the best practice is to use special objects for locks.
source to share