Reputation: 269
If I do
StringBuilder b = new StringBuilder();
b.append("foo").append("bar");
String s = b.toString().intern();
s = null;
Will "foobar"
string created by StringBuilder
be available to garbage collector?
My doubt is about intern()
method, because I am synchronizing some code blocks of application with string based ID.
Something like this:
String id = getUserCurrentId() // this method generates IDs with StringBuider...
synchronized(id.intern()){
// .....
}
It's a desktop application, with some threads, and each logged user owns a generated ID, at each login process.
Upvotes: 3
Views: 397
Reputation: 262834
I think it will work:
While even intern
ed Strings can be garbage collected (so that you might get different instances of your user id over the lifetime of the JVM), they won't be garbage collected while you are inside of that synchronized block (because then the String is still in use), so it should be stable enough for your purposes.
Even if you get another instance next time around, that can only mean that the lock was uncontested anyway, so it does not matter.
But I still would not do this.
How about using a ConcurrentHashMap to get named locks?
Upvotes: 3
Reputation: 115388
When you call str.intern()
you indeed get access to the internal instance of string, i.e. if this sting already in cache you get reference to this instance.
When you say:
String s = .... /* anything */
you create variable that contains yet another reference to the same string. Therefore when you say
s = null;
you just put null
to that reference. It does not affect the object itself. So, it will be removed by GC if GC decides to remove it. You still can use the source object (that one that was written right to the assignment operator) for synchronization. Surely synchronized(id.intern())
looks OK. Although I have no idea why do you want to do this.
BTW re-using objects that have functional meaning in your program for synchronization is a very bad pattern. Think about the following scenario. You are using id.intern()
for syncghronization. This means that if you ID is for example foo
and somebody in other part of the program says
String s = 'foo'
he gets access to the same object because string literals are cached. Now if in other part of the program the following code is written:
String s = 'foo';
.....
synchronized(s) {
s.notify();
}
and in you wrote in your part of the code
synchronized(id.intern()) {
id.wait();
}
probably your wait()
will exit! Such unexpected behavior of the program is very hard to debug. Therefore better practice is to use special objects for locks.
Upvotes: 2