2012-03-24 34 views
1

我一直在困惑于我写的多线程应用程序的问题。简而言之,主线程启动一个热负载线程,该线程接受文件对象的列表(向量),检查其时间戳,并将更改的文件传递给另一个向量。在多线程应用程序中使用向量

当我尝试将新文件添加到需要检查的文件列表时,会发生此问题。热加载线程不断检查其列表中的文件以进行更改,并在迭代时使用范围锁定来锁定/解锁互斥锁。同样,当主线程调用addItems()函数时,同样的互斥锁也同样被锁定,并添加新文件。

我读过的信息说这应该罚款给予适当的锁定,它确实有效,但我经历了一个非常大的减速作为结果。也就是说,如果我连一个文件添加到列表中,该计划不断减慢,仿佛线程越来越锁定...

代码:

void MyThread::addItems(ItemList newItems) 
{ 

    ScopedLock<Mutex> lock(itemMutex_); 


    for (ItemList::iterator it = newItems.begin(); it != newItems.end(); ++it) 
    { 
     if (... test condition on (*it) ...) 
      items_.push_back((*it)); 
    } 
}; 

void MyThread::run() 
{ 
    _done = false; 
    do 
    { 
     YieldCurrentThread(); 

     if (!isEmpty_) 
     { 
      ScopedLock<Mutex> lock(itemMutex_); 
      for (ItemList::iterator it = items_.begin(); it != items_.end(); ++it) 
      { 
       if (... test condition on (*it) ...) 
        updatedItems_.push_back((*it)); 
      } 
     } 
    } 
} 

的run()函数中,当然,不断运行,迭代我的items_vector,并使用从另一个线程调用的addItems()函数将项插入到vector中。只有一个线程调用addItems()。

它不可能是困难的,但我没有看到任何东西在那里,暗示我还没有尝试过的解决方案......

编辑:

  1. 注释如下提醒我指出,如果我不调用addItems(),run()函数似乎对应用程序性能没有任何显着影响,尽管它可能是浪费的。
+0

它被写入的方式,它看起来像updatedItems_将不断地从items_添加相同的项目。 – 2012-03-24 02:35:34

+0

addItems方法未使用items参数。你打算迭代而不是items_? – 2012-03-24 02:42:07

+0

对不起,我修改了代码以方便阅读。在addItems()函数中,我犯了拼写错误。他们已被纠正。关于更新的项目,有一个条件测试,它指示自上次检查文件的时间戳是否发生了变化。如果是这样,它被推送到更新列表,然后传回主线程并清除。 – 2012-03-24 02:53:50

回答

2

你在哪个平台上?如果您正在尝试监视已更改的文件,则有操作系统工具可为您高效地执行此操作。在Linux上,这将是inotify。如果您在Windows上,这看起来像是一篇好文章:http://qualapps.blogspot.co.uk/2010/05/understanding-readdirectorychangesw.html

+0

使用Windows。尽量避免使用特定于操作系统的解决方案,但在这种情况下,我可能会被迫使用它。感谢指针。 – 2012-03-24 02:52:17

+0

当然。对于在Windows上试图解决的问题,有几个调试良好的解决方案 - 您应该接受它们。你的问题从根本上说不是互斥体和向量,而是你正在做的实际处理(可能不需要做)。 – 2012-03-24 02:57:24

+0

好点。我编辑了我原来的帖子来解决这个问题(如果我理解你的意思),但我肯定会开始寻找其他一些解决方案。 – 2012-03-24 03:08:06

1

您的锁定将花费很少的时间解锁。根据YieldCurrentThread的实施方式,如果确实有任何延迟,我认为延迟会非常短暂。而且,列表中的东西越多,平均越长,addItems在将数据添加到矢量之前需要等待的时间越长。如果你的主线花费很多时间拨打addItems,我肯定会有一些放缓。

有一两件事你可以尝试是一个线环,看起来像这样:

for (;;) 
{ 
    ItemList snapshot; 
    if (!isEmpty_) 
    { 
     ScopedLock<Mutex> lock(itemMutex_); 
     snapshot = items_; 
    } 
    ItemList updated; 
    for (ItemList::iterator it = snapshot.begin(); it != snapshot.end(); ++it) 
    { 
     if (... test condition on (*it) ...) 
      updated.push_back((*it)); 
    } 
    if (!updated.empty()) 
    { 
     ScopedLock<Mutex> lock(itemMutex_); 
     updatedList_ = updated; 
    } 
} 

这里的想法是采取重处理,并从互斥下将其移出。当然,如果你的实际瓶颈是锁定争用,这实际上只会加快速度。如果问题只是更多的文件需要更多时间来检查,那么它与多个线程无关。

+0

我很少添加文件。如果我添加一个文件,它会导致应用程序级联放慢 - 控制返回到应用程序所花费的时间显着增加,并且会一直持续下去。迭代过程就是这样做没有意义。否则,+1会有很好的优化! – 2012-03-24 02:51:43

+0

而没有别的东西触及互斥体?读取'updatedList_'的代码怎么样?如果你经常投票,你会反复锁定互斥锁,现在你的主线程和后台线程正在互相攻击。 – 2012-03-24 02:54:36

+0

其实,我有一个单独的互斥体,因为我认为updateList_是一个单独的资源。我从这里排除它,因为我的测试只用addItems()。因此,在这种情况下,在这个线程之外访问资源的唯一地方是在addItems()中。 – 2012-03-24 03:00:09