2013-04-13 29 views
-1

對於此代碼,是否足以同步該方法?非常感謝。同步靜態變量的方法是否夠用了?

class{ 
    private static VariableManager = new VariableManager(); 


    ... 

    static class VariableManager{ 
     private Map<String, Integer> diffCases = new HashMap<String,Integer>(); 
     private int count=0; 

     public synchronized VariableManager get(){ 
      return this. 
     } 

     public synchronized void add(String case, Integer i){ 
      diffCases.put(case, i); 
     } 

     public synchronized void increment(){ 
      c++; 
     } 
    } 
} 

public static synchronized void process(){ 

    ... 
    variableManager.add(case, num); 
    variableManager.count(); 

} 

該程序不能按預期工作,我懷疑這兩個靜態變量不以某種方式保護。當我使用一個線程時,它運行良好。

任何線索?非常感謝。

兩個線程正在處理相同的事件數組,即'eventsArray'。在「過程」方法中,兩個變量在同步方法中被修改。

爲了提供更多一點:

  Thread e1 = new Thread(new EventThread(eventsArray, "e1")); 
     e1.start(); 

     Thread e2 = new Thread(new EventThread(eventsArray, "e2")); 
     e2.start(); 

     e1.join(); 
     e2.join(); 
+3

解釋它如何不按預期工作。嘗試通過調試器運行你的代碼。 – Kninnug

+1

訪問該地圖的任何其他代碼?或計數?你可以發佈嗎? – radai

+1

記住:Hashtable是同步的,而HashMap不是。 – TheEwook

回答

1

看守靜態變量的一致性每個訪問它們必須使用相同同步。這包括讀取變量。如果靜態變量僅用於您向我們展示的方法中,那就足夠了。

如果還有其他地方使用countdiffcases,則必須確保訪問總是使用相同的監視器(即包含靜態變量的類對象)進行同步。如果您只是「閱讀變量」,這也是如此。

*請注意,您的代碼包括:diffcases.add(case)。你不能.add()到地圖。這是真正的代碼嗎?

考慮將靜態變量隱藏在旨在授予對它們的線程安全訪問權的對象中,從而封裝併發感知代碼。在線程之間共享靜態變量通常是錯誤的來源。

+0

如何做到這一點,「考慮將靜態變量隱藏在一個旨在授予線程安全訪問權限的對象中」? – user697911

+0

剛剛糾正。 – user697911

+0

如果對count和diffCases的修改是獨立的並且不需要同步(例如最終一致性足夠),則可以考慮使用ConcurrentMap和AtomicInteger。這些類被設計爲由多個線程同時使用。如果修改必須是同步的,編寫你自己的封裝了一個Map和一個整數的類,並提供(同步!)獲取器和一個像'public synchronized add(case)'這樣的修改方法,該方法原子地放入地圖並增加計數器。 – Pyranja