2014-02-18 39 views
11

當兩個線程同時調用相同的靜態方法時會發生什麼?例如:當兩個線程同時調用相同的靜態方法時會發生什麼?

public static String someMethod(){ 

    //some logic, can take about 1 second to process 

    return new String(result); 
} 

第一個線程現在調用someMethod()。 第二個線程從現在起0.5秒內調用someMethod()(第一個線程仍在處理數據)。

我知道someMethod()可以同步。但是如果不同步會發生什麼?

+0

那麼,這兩個線程將同時運行......如果該方法是線程安全的開始,沒有什麼可怕的。 – fge

+1

如果'static'方法不修改這些線程使用的公共對象的狀態,那麼就沒有錯。 –

+0

[java靜態同步方法]的可能重複(http://stackoverflow.com/questions/12492553/java-static-synchronized-method) – 2014-02-18 20:41:02

回答

10

這取決於您的方法是否更改外部狀態。

static long i = 0l; 
public static String someMethod(){ 
    String accm = ""; 
    for(;i < Integer.MAX_VALUE*20/*Just to make sure word tearing occurs*/; i++) 
     accm += i 
    return accm; 
} 

會引起問題:

  • 多頭不能保證以原子設定,所以他們可能會被 '蹂躪'(Spec
  • ++不是一個原子操作。它是完全一樣的{int n = i; i = i + 1; return n}
    • i = i + 1也沒有原子,如果中間發生變化,一些值會被重複
    • n的回報可能是陳舊

但如果i是一個局部變量,就不會有問題。只要任何外部狀態在閱讀時保證不變,就永遠不會有任何問題。

+0

完全理解,非常感謝:) –

18

當調用某個方法時,JVM將爲執行線程中的調用創建一個堆棧幀。該框架包含在方法中聲明的所有局部變量。在任何方法中,不會訪問字段的靜態或其他方法,每個執行在每個線程上完全獨立進行。如果該方法在其計算中使用參數,則這些參數也位於堆棧幀中,並且多個調用不會相互干擾。

3

該方法是靜態的事實是無關緊要的。他們的問題應該是狀態變量正在被有問題的代碼操縱。

  • 如果沒有任何實例/類的成員被讀/寫,那麼應該沒有問題。
  • 在寫操作的情況下,需要某種同步
  • 如果只有讀取,它並不一定意味着該方法很好地同步。這取決於數據的寫入方式和線程。例如,如果代碼在寫入操作期間讀取受監視器M保護的V,則V的讀取也必須在同一監視器上同步。
0

如果兩個語句在單獨的線程中執行,但也不能保證在第一線的變化將是可見的第二個線程,除非你建立使用同步someMethod()一個之前發生這兩個語句之間關係給定同步策略。換句話說,如果您正在寫入相同的變量並同時從兩個線程中讀取,則您的邏輯可能會給出意想不到的結果。

相關問題