简体   繁体   中英

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 "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.

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 ?

When you call str.intern() you indeed get access to the internal instance of string, ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM