使用lock()防止.NET 6-MVC应用程序中的争用条件



为了缓解.NET 6(Core(应用程序中的竞争状况,我试图锁定一个功能,因此每个用户一次只能访问一次(多个用户可以同时访问,但每个用户只能访问一个(。

正如您在简化代码中看到的,此功能处理汇款,并且转账需要时间。

问题是,如果我一次发送多个请求(来自同一用户(,即使用户没有足够的钱,转账也会发生多次(我认为我的锁应该阻止这种行为,但事实并非如此(。

示例代码:

public async Task<ActionResult> Withdraw()
{
string userId = _userManager.GetUserId(User);
var user = await _userManager.FindByIdAsync(userId);
lock (String.Intern(userId))
{
if(user.HasMoney()){
TransferMoney(); // this one takes time
SendEmail();
}
}

你知道我做错了什么吗?

谢谢!

Web应用程序是无状态的。当接收到客户端的请求时,将为该请求创建相关控制器的实例。当发送响应时,控制器的那个实例就不存在了。

为了防止在旧事务进行时出现新事务,您需要将数据保存在更永久的地方,如数据库。

var lastTransaction = await dbContext.Transactions.Where(t => t.UserId == userId).OrderByDescending(t => t.CreatedDate).FirstOrDefaultAsync();
if (lastTransaction.IsComplete)
{
await Transfer();
await SendEmail();
}
else
{
// tell user it's not ready yet.
}

最新更新