繁体   English   中英

垃圾收集器和String.intern()

[英]Garbage collector and String.intern()

如果我做

StringBuilder b = new StringBuilder();
b.append("foo").append("bar");
String s = b.toString().intern();
s = null;

StringBuilder创建的"foobar"字符串是否可用于垃圾收集器?

我怀疑是关于intern()方法,因为我正在使用基于字符串的ID同步一些应用程序的代码块。

像这样的东西:

String id = getUserCurrentId() // this method generates IDs with StringBuider...
synchronized(id.intern()){
    // .....
}

它是一个桌面应用程序,带有一些线程,每个登录用户在每次登录过程中拥有一个生成的ID。

我认为它会起作用:

虽然即使是实际intern字符串也可以被垃圾收集 (因此您可能在JVM的生命周期内获得用户ID的不同实例),但是当您在同步块内部时它们不会被垃圾收集(因为那时字符串是仍在使用中),因此它应该足够稳定以满足您的需要。

即使你下次再获得另一个实例,这也只能意味着锁无论如何都是无争议的,所以无关紧要。

但我仍然不会这样做。

如何使用ConcurrentHashMap获取命名锁

当你调用str.intern()你确实可以访问字符串的内部实例,即如果这个sting已经在缓存中,你就会得到对这个实例的引用。

当你说:

String s = .... /* anything */

您创建的变量包含对同一字符串的另一个引用。 因此,当你说

s = null; 

你只需将null到该引用。 它不会影响对象本身。 因此,如果GC决定将其删除,它将被GC删除。 您仍然可以使用源对象(直接写入赋值运算符的源对象)进行同步。 肯定是synchronized(id.intern())看起来没问题。 虽然我不知道你为什么要这样做。

BTW重新使用在程序中具有功能意义的对象进行同步是一种非常糟糕的模式。 考虑以下场景。 您正在使用id.intern()进行同步。 这意味着,如果您的ID是例如foo ,而程序其他部分的某人则说

String s = 'foo'

他可以访问同一个对象,因为字符串文字是缓存的。 现在,如果在程序的其他部分编写以下代码:

String s = 'foo';
.....
synchronized(s) {
    s.notify();
}

并在你写的部分代码

synchronized(id.intern()) {
    id.wait();
}

可能你的wait()会退出! 程序的这种意外行为很难调试。 因此,更好的做法是使用特殊对象进行锁定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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