在2个用户线程之间锁定

时间:2019-02-24 05:19:59

标签: multithreading

我有一个创建/销毁对象的主线程。让我们将对象命名为“ f”。 现在,每次创建此对象时,都会将其添加到另一个对象(例如'mi')的尾部队列中。相反,当删除该对象时。 现在,有另一个线程每秒运行一次,试图收集该对象'f'的说统计信息。因此,它基本上遍历了“ mi”的所有最大可能实例(例如2048),然后针对每个这样的“ mi”,收集了所有附加到其上的“ f”对象,将cmd向下发送到下层,该cmd与这些对象相对应的值。现在,它必须使用这些值更新相应的“ f”对象。 现在需要担心的是,如果每1s发生一次遍历,这些“ f”对象之一被主线程删除了,该怎么办? 凭直觉,人们会想到在开始步行之前已获得并在步行/更新属于“ mi”的特定实例的所有“ f”对象后释放的“ mi”级别锁定,对吗? 但是与此有关的唯一障碍是,可能有10,000个甚至数百万个“ f”对象与此“ mi”实例相关联。 另一个要求是创建/销毁这些“ f”对象的主线程性能应很高,即每秒至少10000个对象。 因此,鉴于此,我不确定每个“ mi”对象锁定是否可行?还是我高估了锁争用的副作用? 还有其他想法吗?

1 个答案:

答案 0 :(得分:0)

  

现在关注的是,如果这些“ f”对象之一被删除了,该怎么办   每走1秒就会发生一次行走的主线程?

如果在其他线程尝试使用f对象时将其删除,则将调用未定义的行为,您可能最终将花费数小时来调试程序,以弄清为什么它有时会崩溃。 :)技巧是确保在其他线程正在使用它的同时,不要删除任何f -通常,这意味着您的主线程需要在删除之前锁定mi的互斥量f从其队列中移出–一旦f不再在队列中,则可以在删除f之前释放互斥量,因为这时另一个线程仍然无法访问f

  

我不确定每个“ mi”对象锁定是否可行?

这是可行的,只要您不介意主线程偶尔会被拖延(即阻塞在mutex::lock()方法调用中等待),直到您的其他线程完成对mi的迭代为止s队列并释放互斥体。延迟时间是否可以接受将取决于您的主线程的延迟要求(例如,如果它正在生成报告,则被阻塞数毫秒是没有问题的;如果是在控制界面上运行,则是OTOH)在飞行中的火箭,不能被长时间阻挡都是不能接受的

  

还有其他想法吗?

我的第一个想法是完全摆脱第二个线程-只是让主线程每秒直接调用一次statistics-collection函数。这样,您完全不必担心互斥或互斥争用。这确实意味着您的主线程在运行统计信息收集功能时将无法执行其主要功能,但是至少现在它的“停机时间”是可以预测的,而不是{{{ 1}}对象,这两个线程恰巧在任何给定的瞬间尝试锁定/访问。

如果那不好(即您不能忍受任何显着的延迟时间),则另一种方法是使用消息传递范式而不是共享数据范式。也就是说,不是允许两个线程直接访问同一组mi,而是使用某种消息队列,以便主线程可以使mi退出服务并通过它发送到第二个线程以收集统计信息。然后,第二个线程将照常进行扫描/更新,完成后,将其(通过第二个消息队列)传递回主线程,这将使其重新投入使用。您可以定期使用各种mi来执行此操作,以保持每个更新的统计信息,而无需每个人都需要共享访问它们中的任何一个。 (不过,这仅在您的主线程可以承受短时间内无法访问某些mi的情况下有效)