发布并发对象

时间:2009-07-24 19:27:57

标签: multithreading concurrency hashtable publishing

我对人们用来发布信息和更改数据结构的技术感兴趣,这些数据结构在多个线程中共享而不会丢失很多并发性。根据我的个人经验,我经常遇到单个编写器/多个读者,其中单个线程正在更新对象,但是多个线程正在从对象读取并需要了解更改。

作为一个简单的例子,考虑一个哈希表(让我们假设它是线程安全的,无论是通过粗粒度锁定,细粒度锁定还是低锁技术等)。线程1负责从哈希表中添加和删除信息,但是唯一的编写者。当任何密钥被更改,某个密钥被更改或任何变体时,可能希望通知其他线程。他们希望订阅的内容并不是特别重要。

您会使用哪些技巧(我喜欢论文的建议)来确保线程及时获得正确的更改信息?

2 个答案:

答案 0 :(得分:1)

执行此操作的经典方法是使用等待条件,但它们会阻塞线程直到事件到达。

如今,我将为每个工作线程使用一个消息队列,对中央数据结构的更新将是发布到工作线程队列中的消息。这也是内部使用等待条件,但它是一个比裸等待条件更高级别的接口,并且几乎所有编程语言都有很好的库支持。

一个更为hackish的解决方案是在套接字上的select()调用上阻塞线程,通知线程写入一个字节来唤醒休眠线程。使用select()的优点是,您可以将此类事件与几乎所有其他事件处理进行复用,因此当目标线程例如是GUI线程。

答案 1 :(得分:1)

你实际上已经问过两个不同的问题

MultipleReader / SingleWriter排除

更新通知(通常称为观察者模式)

MultipleReader / SingleWriter Locks是一个CLASSIC问题,其中有大量文献。真正的问题是许多经典解决方案涉及多个互斥锁和信号量,并且可能非常重量级,每个简单的写锁定需要6个读取修改写入(RMW)周期,第一个读取锁定需要6个RMW

这两个问题有很多解决方案,其效率和实用性取决于读取的到达率,写入的到达率,写入的持续时间,读取的持续时间,是否可以批量更新,是否需要升级读锁定,降级写锁定(在你的情况下听起来没有)

对于哈希表的示例,您可以使用“O(n访问线程)的中等粒度锁定,并且只是将锁定任意地分配给哈希表的块(单独链接注意到你。使用开放寻址锁定不会必须锁定被探测到的插槽)。或者你也可以使用hop-scotch哈希并发哈希表算法

就通知而言,一些典型的问题是:

每个读取线程都必须查看(并处理)每个通知吗? 观察者是静态的还是动态的?即通知“网络”是否可以是静态的(编译时定义)