2010-10-24 86 views
18

我有一個使用靜態方法寫入設置xml文件的多線程應用程序。我想避免文件被同時更新兩次(導致訪問/寫入異常)。以靜態方法鎖定()

我該怎麼做?

這不起作用:

namespace Program 
{ 
    public class Settings 
    { 
     private static void SetSettingsValue (string settings, string value) 
     { 
      // make this thread safe to avoid writing to a locked settings xml file 
      lock (typeof(Settings)) 
      { 
       //write data to xml file 
      } 
     } 
    } 
} 
+1

你是否正確地處理了你的XML文件(即通過'using')?你能分享更多的代碼嗎?另外,對於靜態方法,你應該在私有靜態對象上「鎖定」,而不是在類型上。請參閱http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx – 2010-10-24 21:33:30

回答

33

lock()的概念是使用它可以引用的現有對象並用它來控制是否授予訪問權限。

static object SpinLock = new object(); 

lock(SpinLock) 
{ 
    //Statements 
} 

當執行離開鎖()塊引用被釋放,並且任何其他線程正在等待(當然一次一個)來執行碼塊可以繼續進行。

+2

請注意,您不能在lock()語句本身內部更改SpinLock引用。用於鎖定的對象需要由需要執行代碼的所有線程訪問,並且每次都不能更改引用,否則線程將永遠不會彼此阻塞,從而導致資源爭用/衝突。 – 2010-10-24 21:46:47

37

你應該創建一個單獨的,靜態的鎖定對象,並使用它。不要使用字符串!字符串會自動實現,每個程序聲明的字符串只會有一個實例,所以您不能保證對鎖的獨佔訪問。

你應該這樣做:

public class A { 
    private static Object LOCK = new Object(); 

    private static void foo() { 
     lock(LOCK) { 
      // Do whatever 
     } 
    } 
} 

;

鎖定關鍵字(語法可能不正確,我是一個Java的人大多而是鎖定和字符串實習適用於C#同樣的規則)強制執行互斥鎖:一次只有一個線程可以鎖定任何特定的對象。如果第二個線程調用foo,則它將阻塞,直到第一個線程退出鎖定塊。

取回主消息:對私有靜態變量進行靜態方法鎖定。不要鎖定字符串或typeof(...),因爲您無法保證沒有其他人正在使用該對象。總是鎖定一個你認爲不被任何人觸及的物體,將其隱藏起來並使其變爲新的。

+3

這是整個討論中的最佳答案。因爲卡梅隆足夠明智地指出這把鎖是私人的。 – 2010-10-24 21:52:13

+0

它應該也是'final'的C#等價物,但我不是C#的人,所以我不確定那是什麼。如果C#有C++風格的'const',那麼我想我會從Java切換:) – 2010-10-24 21:54:27

+0

不要猜測:http://stackoverflow.com/questions/55984/what-is-the-difference-between-const-and-只讀 – 2010-10-24 22:23:44