【问题标题】:Data access synchronization between multiple threads多线程间数据访问同步
【发布时间】:2010-08-28 18:06:29
【问题描述】:

我正在尝试在 Visual C++ 中实现多线程、递归文件搜索逻辑。逻辑如下: 线程 1,2 将从目录位置开始,并将目录中存在的文件与搜索条件相匹配。如果他们找到子目录,他们会将其添加到工作队列中。一旦线程完成了目录中的文件,它就会从工作队列中获取另一个目录路径。工作队列是一个 STL Stack 类,由用于 push()、pop()、top() 调用的 CriticalSection 保护。

如果堆栈在任何时候为空,线程将在重试之前等待一分钟。同样当所有线程都处于等待状态时,搜索被标记为完成。

这个逻辑没有任何问题,但我觉得我没有获得使用线程的全部潜力,因为与使用单线程相比没有显着的性能提升。我觉得工作堆栈是瓶颈,但无法弄清楚如何消除锁定部分。我尝试了另一种变体,其中每个线程将拥有自己的堆栈,并且仅当本地堆栈大小超过固定数量的工作项时,才会将工作项添加到全局堆栈。如果本地堆栈为空,线程将尝试从全局队列中获取。即使有这种变化,我也没有发现明显的差异。有没有人有任何改进同步逻辑的建议。

问候,

【问题讨论】:

  • 杰瑞,亨克,你们是对的。我按照 Jerry 的建议启动了 perfmon,“平均磁盘队列长度”图跳到 100,并在整个搜索过程中一直保持在那里。添加另一个线程有一点帮助的唯一原因是涉及到文件名比较。

标签: multithreading visual-c++ stl thread-safety critical-section


【解决方案1】:

我真的怀疑你的工作堆栈是瓶颈。磁盘只有一个磁头,一次只能读取一个数据流。只要您的线程处理数据的速度与磁盘可以提供的速度一样快,那么您可以做的其他事情就不会对整体速度产生任何重大影响。

对于其他类型的任务,您的队列可能会成为严重的瓶颈,但对于这个任务,我对此表示怀疑。请记住此处操作的时间尺度。在 CPU 内部发生的一个简单操作需要不到一纳秒的时间。从主存储器读取需要几十纳秒的时间。诸如线程切换或同步之类的事情大约需要几百纳秒左右。磁盘驱动器上的单个磁头移动大约需要一毫秒(1,000,000 纳秒)。

【讨论】:

  • 谢谢杰瑞。有没有办法检查磁盘读取是否已经在 Windows 机器上被最大限度地使用。
  • @ivymike:您可以使用性能监视器来查看您正在使用多少磁盘带宽,但这不会告诉您理论上的最大带宽。如果内存够用,您还可以检查磁盘队列深度以了解是否有 I/O 命令等待执行。你并不关心确切的队列深度,只是它(几乎)几乎非零(这里我说的是操作系统的队列,而不是你的)。
【解决方案2】:

除了@Jerry 的回答,你的瓶颈是磁盘系统。如果您有一个 RAID 阵列,您可能会看到使用 2 或 3 个线程的一些适度改进。

如果您必须搜索多个驱动器(注意:物理驱动器,而不是单个物理驱动器上的卷),您可以为每个驱动器使用额外的线程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    相关资源
    最近更新 更多