【问题标题】:Multithreading - In an array what should I protect?多线程 - 在数组中我应该保护什么?
【发布时间】:2013-02-17 19:44:18
【问题描述】:

我正在编写一些具有全局数组的代码,该数组可以被两个线程访问以用于读写目的。

在读取或写入一系列索引的情况下不会进行批处理,因此我试图确定是应该锁定整个数组还是只锁定我当前使用的数组索引。

最简单的解决方案是将数组视为 CS 并在其周围放置一个大锁,但我可以避免这种情况并只锁定一个索引吗?

干杯。

【问题讨论】:

  • 你可以。如果这不是您所期望的答案,改进问题应该会导致改进的答案。
  • 您必须自行决定什么是要锁定的“逻辑”数据分组(然后确定如何按组锁定)。
  • 我认为您需要使用真实的运行场景进行分析,以确定您锁定的粒度级别。
  • @ring0 - 这将取决于阵列上的内容。就像 32 位系统上的 64 位变量一样简单,并且不再是原子的了
  • 我假设的是基本类型。对于更复杂的类型,每 100 个索引一个信号量:lock sem[index/100]... 会减少内存使用量。

标签: c++ c multithreading thread-safety pthreads


【解决方案1】:

锁定一个索引意味着您可以跟踪哪个线程正在访问数组的哪个部分。跟踪在读取和写入线程之间共享的此信息意味着您对该信息有一个锁定。所以,你最终还是会得到一个全局锁。 在这种情况下,我认为最有效的方法是: - 使用读/写锁 - 或者将大数组分成几个子集,每个子​​集使用不同的锁。

【讨论】:

  • @Candag:当然不是!一个线程只需要知道确定哪个锁与数组的目标子集相关联的简单方法。
  • @Candag:请参阅 ring0 对该问题的评论,了解将信号量或互斥体映射到 100 个数组元素范围的简单可能性。如果您的线程倾向于处理非常接近的数组元素,您可以执行mutex_arr[idx%16] 之类的操作,将每个互斥体映射到每 16 个数组项。
【解决方案2】:

如果这是 C++,我建议您使用 STL 容器。 std::vector 或其他适合您工作的东西。它们速度快、易于使用、没有内存泄漏。

如果您想自己做这一切,那么当然一种方法是使用单个互斥锁(这很糟糕)。 或者你可以为整个数组使用一些reader writer thingy

我认为用自己的锁使数组线程的每个元素都安全是不可行的!那会吃掉你的记忆。检查链接,有 3 种不同的解决方案。测试它们并为您的情况使用最好的。 (不要想“好吧,我认为我的程序需要读者偏好算法”。尝试在您的系统中使用它并决定。因为我们真的不能假设这样的事情有时

【讨论】:

  • 标准库容器,特别是提到的std::vector<>,对于除独占读取之外的任何内容不是线程安全的。因为它们与Type ar[N] 块没有什么不同。一旦介绍了作者,您必须提供某种保护(互斥锁等)。
  • 即使它是一个向量,我也不能在同一个索引上读写。但是对于向量,我们还有其他问题 (shortbytes.blogspot.pt/2012/08/whats-wrong-with-vectors.html)
  • 我认为您应该在这里澄清 thread safe 的含义,因为 OP 可能会认为std::vector 在编写线程时是安全的,但事实并非如此一点也不。一旦其中一个线程正在写入,线程安全就会消失。
  • @juanchopanza:好点。我编辑并删除了那部分。
【解决方案3】:

除非您在真实的运行条件下进行分析,否则无法知道什么是最佳的。我建议实现一个类似数组的类,您可以在其中锁定组中不同数量的元素。然后微调这些组的大小。

另一种选择是使用active object 将所有读/写操作排入队列。这将使所有访问都按顺序进行,并且意味着您可以使用非并发数组类型来存储数据。它需要某种并发队列数据结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2017-11-29
    相关资源
    最近更新 更多