在一個c#程序中,我有兩個線程啓動一個存儲過程。 該存儲過程在某些表中讀取和寫入數據。多線程程序中的Sql服務器鎖異常
當我開始我的計劃,我有時SQL服務器異常(鎖定麻煩)。
爲了避免死鎖,我想在我的程序,以避免此存儲過程的成功(同一除外),但沒有同時呼叫
如何修復添加lock(this){ ... }
?
在一個c#程序中,我有兩個線程啓動一個存儲過程。 該存儲過程在某些表中讀取和寫入數據。多線程程序中的Sql服務器鎖異常
當我開始我的計劃,我有時SQL服務器異常(鎖定麻煩)。
爲了避免死鎖,我想在我的程序,以避免此存儲過程的成功(同一除外),但沒有同時呼叫
如何修復添加lock(this){ ... }
?
lock(this)
不會解決你的併發問題,如果類的多個實例正在運行,因爲鎖會參考不同this
引用,即
public class Locker
{
public void Work()
{
lock (this)
{
//do something
}
}
}
用作(假設這些代碼中運行並行)
Locker first = new Locker(); Locker second = new Locker();
first.Work() // <-- locks on first second.Work() // <-- locks on second
將鎖定在不同的對象上,而不是完全鎖定。
使用這種模式
public class Locker
{
private static object lockObject = new object();
// a static doodad for locking
public void Work()
{
lock (lockObject)
{
//do something
}
}
}
將鎖定在兩種情況下,同樣的事情,並進行第二個呼叫等待。
但是,從我的經驗,多數情況下,在SQL Server程序鎖定問題是程序本身的故障,持有交易比neccessary開放的時間越長,開不必要的交易,有次優查詢等讓您的SP調用在C#代碼中排隊等待,而不是在SQL Server中排隊,並不能解決這些問題。
另外,死鎖是併發性問題的一個特定的類別,幾乎總是可以通過重構時考慮到數據訪問的解決方案來解決。給我們提供關於這個問題的更多信息,可能有一個解決方案根本不需要應用程序級鎖。
正如@SWeko所解釋的那樣,C#的lock
只能解決當前AppDomain的線程之間的併發問題,所以如果有多個AppDomain在運行,爲了簡單起見我們說兩個桌面客戶端,然後它們將會陷入死鎖。有關更多詳細信息,請參閱Cross-Process Locking in C#和What is the difference between lock and Mutex?。
它會好得多,即使在桌面應用程序的情況下,你處理死鎖問題您的存儲過程中。默認行爲是您的第二個請求會等到第一個完成的超時,如果您不想等待,請使用WITH(NOWAIT)
。 Explore more
如果你能證明在SP代碼這將是一個更容易弄清楚爲什麼你得到一個僵局。 – 2011-04-06 13:13:05