【问题标题】:concurrent access and free of a data structure并发访问且无数据结构
【发布时间】:2012-02-02 16:22:35
【问题描述】:

问题是这样的:

我有一个包含 500 个指针的数组,它们指向双向链表中的 500 个元素。有 10 个线程并行运行。每个线程运行 50 次循环,并尝试释放列表中的某些元素。

列表已排序(包含简单整数),还有10个其他线程并行运行,搜索包含特定整数的节点并访问该节点中的其他卫星数据。所以节点是这样的:

struct node
{
   int key;         // Key used to search this nodes
   int x,y,z;       // Satellite data
   struct node *prev;
   struct node *right;
};

如果我在搜索/删除之前锁定列表,问题很容易解决。但这太粗粒度了。如何同步这些线程,以便获得更好的并发性?

编辑:

  1. 这不是家庭作业问题。我不属于学术界。
  2. 包含 500 个指针的数组看起来很奇怪。我这样做是为了以尽可能低的复杂性可视化我的问题。

【问题讨论】:

  • 确实是重复的。我的问题更详细地解释了这个场景。
  • 可能的最佳并发 将非常密切地取决于您的确切访问模式,这从问题中并不清楚。您是否有 10 个线程基本上遍历同一个链表,每个线程都在寻找要删除的不同键?如果是这样,为什么 - 比较 500 个整数需要多长时间?
  • 我编辑了这个问题。一共有20个线程。 10 个删除线程和 10 个搜索线程。搜索线程通过遍历列表进行搜索。删除线程直接删除列表中存在的指针。这个问题只是代表性的,我正在寻找比粗粒度锁更好的东西。
  • 所以 - 删除线程正在从列表中删除随机项目,您不希望这样会阻碍搜索者,是吗?

标签: c multithreading memory-management concurrency


【解决方案1】:

我可以想到几种不涉及全局锁定的广泛方法,并且应该允许某种程度的前进:

1。标记但不删除

当删除线程识别出它的受害者时,将其标记为已删除但将其保留在原处。 当搜索线程遇到带有此已删除标记的节点时,它会忽略它。

您需要在标记节点已删除后发出写入/释放屏障,并在检查值之前发出获取屏障:您需要特定于平台、特定于编译器的扩展,否则您将这些屏障写入汇编程序。

2。使用无锁列表进行真正的删除

根据 Peeyush 回答中的论文; CAS 的类似平台或编译器特定要求,并且需要非常小心。诸如引用计数或危险指针之类的选项可以允许在没有人查看节点时真正删除该节点。您可能会发现您需要将您的 prev/next 指针替换为 short 索引,您可以将它们打包成一个单词以便 CAS 工作:这意味着限制节点的数量并将它们分配到一个数组中。

还请注意,虽然每个线程都应该能够使用这种方案取得进展,但由于同步要求,单个操作(例如遍历到下一个节点)可能会变得更加昂贵。

【讨论】:

  • 谢谢。第一种方法对我不起作用,因为删除线程的目的是重新获得内存。
  • 在第二种方法中,我将寻找 CAS 解决方案。基本上我还没有想出一个策略来保持节点内部的锁。并同时读取和释放它。
  • 如果您的一致性要求足够宽松,则可以使用混合方法:例如,将其从列表中删除(使用发布语义)并让每个搜索者在开始新搜索时发出获取障碍。最终没有搜索线程会遍历它,您可以回收内存。但与此同时,它可能看起来不同(即,在一个方向上链接而不是在另一个方向上)。
  • 由于这只是冒泡,请注意,自 C++11 以来,您可以使用 std::atomic 完成所有这些操作(在编写此答案之前,我一直在使用 C++0x,但显然不是t 已完成且支持不完整。当时我当然仍在使用内联汇编或内置函数,而不是 std::atomic)。
【解决方案2】:

您可以考虑使用 CompareAndSwap 操作的无锁链表。

link to paper

【讨论】:

    【解决方案3】:

    您需要锁定任何可以更改的数据。如果您要做大量工作,请为列表中的每个项目创建一个锁。线程必须锁定前一项、当前项和下一项才能删除中间项。确保始终以相同的顺序获取锁以避免死锁。

    其他删除线程和搜索线程必须等到对象被删除并建立新链接。然后锁被释放,它们可以继续。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      相关资源
      最近更新 更多