我最近遇到了一个基于多线程的问题。我遇到了一种情况,那里会有不变的汽车不断改变那里的位置。此外,还有多个用户在任何时刻发布请求以获取任何汽车的位置。处理这种情况的数据结构是什么?为什么?
答案 0 :(得分:0)
您可以使用互斥锁(每辆车一个)。
锁定:在更改相关汽车的位置之前
解锁:更改相关车辆的位置后
锁定:在获取相关汽车的位置之前
解锁:完成依赖该位置最新的工作后
答案 1 :(得分:0)
我回答:
尝试将线程化作为系统的外部概念,同时使系统尽可能模块化并封装。它将允许在后期以低成本添加并发,并且如果解决方案恰好在单个线程中工作(例如,通过使其基于事件循环),没有时间会被烧毁。
答案 2 :(得分:-1)
有几种方法可以做到这一点。您选择哪种方式很大程度上取决于汽车数量,更新频率和位置请求,预期响应时间以及您希望位置报告的准确性(最新)。
处理此问题的最简单方法是使用简单的互斥锁(锁),一次只允许一个线程访问数据结构。假设您正在使用字典或哈希映射,您的代码将如下所示:
Map Cars = new Map(...)
Mutex CarsMutex = new Mutex(...)
Location GetLocation(carKey)
{
acquire mutex
result = Cars[carKey].Location
release mutex
return result
}
您可以为添加,删除,更新等执行此操作。任何读取或更新数据结构的方法都需要您获取互斥锁。
如果查询的数量远远超过更新的数量,那么您可以使用读取器/写入器锁而不是互斥锁来做得更好。使用RW锁定,您可以拥有无限数量的读者,或者您可以拥有一个写入者。有了它,查询数据将是:
acquire reader lock
result = Cars[carKey].Location
release reader lock
return result
添加,更新和删除将是:
acquire writer lock
do update
release writer lock
许多运行时库都内置了并发字典数据结构。例如,.NET具有ConcurrentDictionary
。有了这些,您不必担心使用Mutex或RW锁显式同步访问;数据结构为您处理同步,使用类似于上面显示的技术,或通过实现无锁算法。
正如评论中所提到的,关系数据库可以很容易地处理这种类型的事情,并且可以扩展到非常大量的请求。现代关系数据库,正确构建并具有足够的硬件,速度惊人,并且可以以非常高的吞吐量处理大量数据。
还有其他更复杂的方法可以在某些情况下提高吞吐量,具体取决于您尝试优化的内容。例如,如果您愿意在报告的位置中有一些延迟,那么您可以从列表中提供位置请求,该列表每分钟更新一次(或每五分钟更新一次)。因此,位置请求立即得到满足,并且每分钟更新一次的列表的静态副本不需要锁定。更新排队,每分钟一次,通过将更新应用于旧列表来创建新列表,新列表可用于请求。
有许多方法可以解决您的问题。