簡體   English   中英

Java:StringBuilder,靜態方法和可能的同步問題

[英]Java: StringBuilder, static method and possible synchronization issues

像這樣的代碼是否可能不是線程安全的? 它是一個靜態方法,我們使用的是stringbuilder的本地實例。 我猜輸入字符串可能被其他對象保存?

public static String cat(final String ... strings) {

    ...
    ...
    final StringBuilder sb = new StringBuilder(totLength);
    for (int i = 0; i < size; i++) {        
        if (strings[i] != null) {
            sb.append(strings[i]);
        }
    }
    return sb.toString();
}

它不是完全線程安全的 - 因為另一個線程可能正在更改在strings參數的參數中傳遞的相同數組。 由於您使用了varargs,這並不完全是顯而易見的,但有效地(就線程安全而言)方法簽名只是:

public static String cat(String[] strings)

它不會導致任何異常,但您可能看不到數組中的最新值。

作為另一種選擇,如果它確實看到了變化,您可能會看到意外的事情。 例如,假設我們只傳入一個單值數組,其值最初為“x”:

public static String cat(final String ... strings) {    
    ...
    ...
    final StringBuilder sb = new StringBuilder(totLength);
    for (int i = 0; i < size; i++) {
        // strings[0] is currently "x"
        if (strings[i] != null) {
            // But now another thread might change it to null!
            // At that point we'd get "null" as output
            sb.append(strings[i]);
        }
    }
    return sb.toString();
}

換句話說,雖然您可能希望看到“x”或“”作為結果,但您可以看到“null”。 為了解決這個問題,你可以從陣列讀取每個值只有一次

final StringBuilder sb = new StringBuilder(totLength);
for (int i = 0; i < size; i++) {
    String value = strings[i];
    if (value != null) {
        sb.append(value);
    }
}

您可能仍然會看到一個數組在更改的一半(例如,如果一個線程正在將{"x", "y"}更改為{"a", "b"}您可能會看到“xb”作為結果),但你不會得到虛假的“空”。

這應該是線程安全的,因為傳入的字符串是不可變的。 假設你在方法中創建了totLength ,其他一切都是本地的。

編輯:

正如Jon Skeet指出的那樣 ,vargs值有可能不僅作為一個字符串序列傳遞(如我的答案所假設的那樣),而且還可以傳遞給String[] 在后一種情況下,有可能在處理時由另一個線程修改數組。

不,它是寫的(*)線程安全的。 字符串是不可變的,因此多個線程調用它並不重要。

(*代表您顯示的代碼)

即使你沒有傳遞不可變對象,這也是線程安全的,因為

  • 你沒有改變任何輸入參數
  • 你唯一要改變的是局限於方法的局部范圍。

請參閱John Skeet對陣列部分的回答。

至於StringBuilder ,它應該是安全的。 因為StringBuilder是在方法內創建的,所以每個調用都有自己的StringBuilder

StringBuilder本身不是同步的,所以如果它在靜態方法調用之前存在,那么最好使用StringBuffer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM