[英]Why does lock(this) thread.sleep not work with ASP.NET threading?
[英]Why this lock does not work in service, called from asp.net?
我繼承了一個具有服務類的應用程序,該服務類是從asp.net應用程序調用的,如下所示:
class PeopleService : IPeopleService
{
//...
public void SavePerson(Person person)
{
person.UniqueId = _idGenerationService.GetNextId(person);
//...
_dbContext.InsertOrUpdate(person);
_dbContext.Commit();
}
}
class IdGenerationService : IIdGenerationService
{
//...
public string GetNextId(Person person)
{
int nextId = _dbContext.People.Count(x => x.Gender == person.Gender) + 1;
return string.Format("AB{0}", nextId);
}
}
GetNextId(Person)
的實現不是線程安全的,並且我們有很多具有重復ID的Person對象,例如AB1,AB2,AB2等。
解決方案是將lock
應用於SavePerson(Person)
如下所示:
class PeopleService : IPeopleService
{
private static readonly Object ReadIdLock = new Object();
//...
public void SavePerson(Person person)
{
lock(ReadIdLock)
{
person.UniqueId = _idGenerationService.GetNextId(person);
//...
_dbContext.InsertOrUpdate(person);
_dbContext.Commit();
}
}
}
現在,我們嘗試通過在asp.net應用程序中同時單擊“保存”按鈕來測試代碼。 但是修復沒有用! 有趣的是,只有第一個記錄似乎是重復的,例如AB1,AB1,AB2,AB3 ...
多個請求如何訪問鎖定的語句? 我應該改用Mutex
嗎?
(請注意,該示例不是生產代碼,它是一個簡化的代碼,可以傳達我們遇到的問題。此外,一點點,我們將StructureMap用作DI)。
由於鎖是一個靜態變量,因此每個appdomain中只有一個這樣的鎖對象,它排除了許多可能的錯誤。 這是我能想到的唯一問題的原因:
您的鎖只能在一個appdomain中使用。 ASP.NET可以同時在多個應用程序域中運行應用程序,例如在回收,部署或以網絡花園模式運行時。 另外,您可能有多個服務器。
最好的解決方法是使_idGenerationService.GetNextId
線程安全的。 可能您需要對作為此方法基礎的數據庫查詢應用適當的鎖定。
另外,您鎖定的區域太長。 您還將覆蓋插入到數據庫中。 這會使並發性不足,並可能導致分布式死鎖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.