想想看电影票。有x个开放式座位,当你来到现场时,我想预留一个座位一段时间。
我有一个私有内部API和一个公共API。公共API将通过调用内部API然后将该席位置于“正在预订”状态来响应寻求预订座位的应用程序。
我的问题是我偶尔会有两个人预订同一个座位,导致一个人输入所有信息,然后无法完成注册。
我试图让我的代码线程安全,但仍然得到同一个席位的奇怪重复分配。
我从我的“预约”方法调用状态更新:
VisitStatusChangeResult visit_status_change_result = await ReserveSlotByLockedStatusUpdate(first_empty_seat);
这是状态更新方法,我尝试使用SemaphoreSlim添加线程安全性:
private static SemaphoreSlim m_ReserveOnlineSlotStatusUpdateSemaphore = new SemaphoreSlim(initialCount: 1, maxCount: 1);
private async Task<VisitStatusChangeResult> ReserveSlotByLockedStatusUpdate(VisitQueryResult first_empty_seat)
{
await m_ReserveOnlineSlotStatusUpdateSemaphore.WaitAsync();
try
{
return await ChangeStatus(new VisitStatusUpdateModel
{
VisitID = first_empty_seat.ID,
CurrentVisitStatusID = first_empty_online_visit.VisitStatusID,
NewVisitStatusID = (int)VisitStatuses.BeingBooked
});
}
finally
{
m_ReserveOnlineSlotStatusUpdateSemaphore.Release();
}
}
我错过了一些即使SemaphoreSlim等待的事情,我可以让两个人抓住同一个座位吗?
答案 0 :(得分:1)
首先,使用内存中的锁来保护对数据库资源的并行访问并不是一个好主意 - 每个数据库都有自己的工具来处理这些事情。在这种情况下,您很可能必须使用乐观并发,大致如下:
update Visit set VisitStatusID = BeingBooked, ClientID = CurrentClientID where VisitStatusID = Free
所以你知道谁现在正在预订这个座位,而且,如果发生这个座位已经不是免费的话 - 这个陈述将返回0(0行修改)。您应该检查并采取相应措施(通知客户已经采取了这个座位并刷新座位)。
其次,你的锁无论如何都没有效果。没有什么能阻止两个客户端一个接一个地调用ReserveSlotByLockedStatusUpdate
,并且仍然遇到麻烦,因为他们都会保留相同的席位(除非你实现上面的乐观并发)。 / p>