簡體   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