我开发了一个在线购买我的产品的应用程序。 我的商店里有一个产品“雨伞”,有 100 件。我开发了一个在线购买我的产品的应用程序。 但是当有并发购买时会出现问题。
如果同时发生两个采购,AvailableQty 将错误更新。假设有两笔交易同时发生,采购数量分别为 100 和 50。理想情况下,第一笔交易(采购数量为 100)应该成功,因为我们有 100 只股票可用。但是第二笔交易应该返回错误,因为库存不足以处理第一笔交易,余额为 0。 (100 - 100)。但是在上面的场景中,两笔交易都成功了,现在余额显示为-50。
当有两个单独的事务时,这将正常工作。但当这两笔交易同时发生时,这是一个问题。这个问题的原因是,当并发事务检查可用性的条件同时命中时,由于数据库表没有更新最新的数量,此时条件被满足。
我该如何纠正这个问题?
public bool UpdateStock(int productId, int purchaseQty)
{
using(var db = new MyEntities())
{
var stock = db.Products.Find(productId);
if (stock.AvailableQty >= purchaseQty) // Condition to check the availablity
{
stock.AvailableQty = stock.AvailableQty - purchaseQty;
db.SaveChanges();
return true;
}
else
{
return false;
}
}
}
最佳答案
这是典型的线程并发问题,可以通过多种方式解决,其中之一是使用简单的 lock
语句:
public class StockService
{
private readonly object _availableQtyLock = new object();
public bool UpdateStock(int productId, int purchaseQty)
{
using (var db = new MyEntities())
{
lock (_availableQtyLock)
{
var stock = db.Products.Find(productId);
if (stock.AvailableQty >= purchaseQty) // Condition to check the availablity
{
stock.AvailableQty = stock.AvailableQty - purchaseQty;
db.SaveChanges();
return true;
}
return false;
}
}
}
}
只有一个线程可以获得在_availableQtyLock
上获得锁的独占权,这意味着其他线程将不得不等待第一个线程释放对该对象的锁。
考虑到这是处理并发的最简单(也可能是最慢)的方法,还有其他方法可以进行线程同步,例如Monitor
、Semaphore
、快速 SlimLock
等...因为很难说出哪一个最适合您的需求,您需要进行适当的性能/压力测试,但我的建议是从最简单的开始。
注意:正如其他人在评论中提到的,并发问题也可以在数据库级别完成,这确实更合适,但如果您不想/不能引入任何数据库更改,这将是一种方式走
关于c# - 更新并发事务 C# 的数量问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53185716/