2013-09-25 80 views
6

如果我有一個函數編輯我的web服務中的數據庫,我只希望一次執行一個線程,如果他們嘗試編輯同一行。只有當值相同時才鎖定?

void EditCheck(long checkid) 
    { 

     if (isCheckCosed) 
      throw new Exception("check is already closed"); 

     //do stuff 

     //after i edit my check i want to close it. 
     CloseCheck(); 
    } 

我知道我可以鎖定全功能,但後來我鬆散的性能與特點,因爲它幾乎從來沒有不同的線程將嘗試編輯相同的檢查。

有沒有辦法只鎖定其他線程具有相同的checkid?

UPDATE

我使用OleDbConnectionMySqlConnection

OleDbCommand oleDbCommand = AccessTrans != null ? 
new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn); 
oleDbCommand.ExecuteNonQuery(); 

相同功能爲MySqlCommand

,然後我強制使用正常的插入和更新SQL命令。 並檢查交易是否存在。所以如果你想要一個事務或者不在你的上層函數中這個函數可以工作。

從數據庫中讀取我要填補DataTable

OleDbCommand oleDbCommand = AccessTrans != null ? new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn); 
OleDbDataAdapter dAdapter = new OleDbDataAdapter(); 
dAdapter.SelectCommand = oleDbCommand; 
dAdapter.Fill(dTable); 
return dTable; 
+2

不應該在數據庫端處理這個問題嗎?你真的有問題嗎?還是僅僅基於假設? –

+0

如何寫入數據訪問?如果你使用EF這可能會有所幫助:http://blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concurrency-in-the- entity-framework.aspx – Lev

+1

你能說明你是如何訪問數據庫的嗎?有很多好的工具內置到許多數據訪問方法中來處理這個問題(只有一個客戶端連接到數據庫時,客戶端發生的任何解決方案纔會工作。如果你的程序的兩個副本都調用'EditCheck'作爲相同的'checkid',那麼當前的答案將不起作用) –

回答

13

可以使用ConcurrentDictionary映射每個ID的對象,您可以鎖定:

public class Foo 
{ 
    private ConcurrentDictionary<long, object> dictionary = 
     new ConcurrentDictionary<long, object>(); 

    private void EditCheck(long checkid) 
    { 
     var key = dictionary.GetOrAdd(checkid, new object()); 
     lock (key) 
     { 
      //Do stuff with key 
     } 
    } 
} 
+0

不錯。對[這個答案]的改進(http://stackoverflow.com/a/781324/571637) – jltrem

+0

感謝您的回答,我將閱讀ConcurrentDictionary並測試它。但似乎只是我需要的。 – Dendei

+0

如果你要有很多線程只進行只讀操作,你也可以試着使用[ReadWriterLock](http://stackoverflow.com/questions/2116957/readerwriterlock-vslock)同時在'checkid'上,這會讓多個線程都在相同的'checkid'上執行讀操作,但是一旦有人想寫它,就會鎖定所有併發讀取器。 –

0

當你想提高性能,你應該儘可能在最近的時候鎖定。在您使用數據庫時,您可以使用數據庫鎖定。你有兩個選擇:

  1. 使用Select for update,看Proper way to SQL select and update
  2. 使用樂觀鎖定這是恕我直言,做最好的辦法是,http://en.wikipedia.org/wiki/Optimistic_concurrency_controlhttp://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html

注意,這兩種方法可以讓你用DB資源多於程序化資源。爲什麼這個建議的字典更好呢?

一旦您將複製數據,數據庫中的數據將複製到運行時字典中,您將被迫同步它們,因此如果有人更新數據庫並添加新數據庫,則需要立即更新字典。

當然,這對小維護(例如存儲庫)類是可行的,但是一旦你的項目發展壯大,你的一些同事可能會忘記這些信息,並且你會開始發現這樣的錯誤。

相關問題