我用 C# 编写的服务器应用程序每次需要从数据库中插入或删除数据时都会启动一个新线程。问题在于,由于线程的执行是任意的,因此如果这些事件几乎同时发生,则不能确保在插入同一对象之后执行删除命令。
例如:服务器接收到插入多个对象的命令。插入所有对象大约需要 5 秒钟。执行 1 秒后,服务器收到从数据库中再次删除所有这些对象的命令。由于删除可能发生在所有对象完全存储之前,结果是未知的。
如何管理某个线程的执行顺序?
我用 C# 编写的服务器应用程序每次需要从数据库中插入或删除数据时都会启动一个新线程。问题在于,由于线程的执行是任意的,因此如果这些事件几乎同时发生,则不能确保在插入同一对象之后执行删除命令。
例如:服务器接收到插入多个对象的命令。插入所有对象大约需要 5 秒钟。执行 1 秒后,服务器收到从数据库中再次删除所有这些对象的命令。由于删除可能发生在所有对象完全存储之前,结果是未知的。
如何管理某个线程的执行顺序?
您可以为此使用事务并为不同的操作指定不同的级别。
例如,您可以将最高级别的事务用于写入/更新/删除,而将低级别的事务用于读取。与表相比,您还可以对其进行微调以允许仅阻止特定行。具体术语取决于您使用的数据库和数据访问库。
我建议不要使用任何排序。并行和有序只是不能很好地结合在一起。例如:
您需要水平扩展服务器,一旦添加第二台服务器和负载平衡器,互斥解决方案将无法正常工作
在大型和分布式系统中,消息队列也不会工作,因为当一个线程完成扫描并决定我们可以开始时,另一个线程可以写入一条应该阻止操作执行的消息。此外,如果您收到高负载,多次扫描同一个队列是低效的。
如果您知道您在删除之前收到了插入,而问题只是您不想中断插入,那么您可以在插入代码上使用锁定。
static object m_Lock = new object();
public void Insert()
{
lock (m_Lock)
{
InsertRecords();
}
}
public void Remove()
{
lock (m_Lock)
{
RemoveRecords();
}
}
这样您就可以确保在插入期间不会发生删除。
PS 虽然您需要立即插入然后删除,但这似乎很奇怪。
我认为最简单的方法是将所有传入请求排队以在一个集合中插入对象,并将所有传入请求排队以删除第二个集合中的对象。
服务器应该有一个基本循环:
一种。检查是否有传入的插入,如果有 -> 执行所有插入。
湾。检查是否有传入的删除请求,如果有 -> 执行所有删除请求。
C。睡眠 X 毫秒。
现在,如果您对不存在的对象有删除请求。你有两个选择:
一种。忽略此请求并丢弃它。
湾。忽略这一轮的这个请求,并在接下来的 N 轮中将其保留在集合中,然后再删除它(最后删除它 - 假设这只是一个错误的请求,而不是竞争条件的问题。)
使用队列(带有单个服务线程)来强制执行排序。您还可以使用任务并行库来管理依赖于其他任务的任务,尽管这对于任意 DB 操作来说非常困难。
我认为您需要重新考虑如何管理传入的操作,以及它们的相互依赖关系是否足够可预测,以至于您可以以这种方式安全地使用多个线程。您可能需要在传入操作中添加一些“取决于”信息以实现该目标。