2010-04-22 26 views
8

對同一對象使用嵌套鎖的性能代價是多少?對同一對象性能的嵌套鎖

說我們有:

public void AddRange(IEnumeratable<Item> items) 
    { 
     lock (_syncObject) 
     { 
      foreach (Item item in items) 
      { 
       InsertItem(item); 
      } 
     } 
    } 

    public void InsertItem(Item item) 
    { 
     lock (_syncObject) 
     { 
      //.. 
     } 
    } 

它是確定這樣做 「性能方面」?

在此先感謝。

回答

6

鎖具有成本,我建議你去實現你這樣的代碼:

public void AddRange(IEnumeratable<Item> items) 
{ 
    lock (_syncObject) // Locking only once. 
    { 
     foreach (Item item in items) 
     { 
      InsertItemImpl(item); 
     } 
    } 
} 

private void InsertItemImpl(Item item) 
{ 
    // inserting the item 
} 

public void InsertItem(Item item) 
{ 
    lock (_syncObject) 
    { 
     InsertItemImpl(item); 
    } 
} 
2

lock不是免費的。它在返回之前檢查某些事情。有多少事情要做,取決於實施。我會猜想,這種用法很常見,MS爲這個用例做了一些優化。

我仍然建議您在單次完成所有工作的情況下分別實施AddRange。這當然取決於該類的其他接口(是否有聽衆,他們是否可以接收添加了多個對象的消息等)。

這是相當簡單的測試用例,做了幾百萬的嵌套鎖定(你建議的)和其他鎖相同。

還要注意不同的可能的順序,如果你使用非嵌套鎖,您可以在您要添加的一系列中間得到一個對象:

AddRange _sync1 
    AddItem _sync2 
    AddItem _sync2 
    --- interruption, other thread calls: 
    AddItem _sync2 
    --- AddRange again: 
    AddItem _sync2 

如果使用單個_syncObject同步,沒有人能中斷因爲鎖已經被另一個線程佔用。

1

我不知道該如何影響性能,但是當我們期望它會降低性能我建議你實現你的代碼的其他方式:

public void InsertItem(Item item) 
{ 
    AddRange(new IEnumeratable({item})) 
} 

public void AddRange(IEnumeratable<Item> items) 
{ 
    lock (_syncObject) 
    { 
     foreach (Item item in items) 
     { 
      // Insert code .. 
     } 
    } 
} 

@AddRange(新IEnumeratable({項目})): 我不是一個語法wizkid所以請糾正我,如果這是不正確的!

+3

我覺得這是更好地執行插入移動到另一個方法,而然後爲每個加入項目創建新的集合。 – 2010-04-22 16:37:33