2013-02-18 45 views
1

我正在处理中间处理线程的生产者消费者问题。当我运行这些应用程序中的200个时,它会在大量连接超时时将系统锁定在win7中。不幸的是,我不知道如何调试它。系统无响应,我必须使用电源按钮重新启动。它可以在我的Mac上正常工作,奇怪的是,它在安全模式下的窗口中工作正常。如果足够的活跃,可以boost :: mutex锁定一个操作系统吗?

我使用boost 1.44,因为这是主机应用程序使用的。

这是我的队列。我的意图是队列的大小是同步的。我已经操纵这个来使用timed_wait来确保我没有丢失通知,尽管我没有看到效果上的差异。

class ConcurrentQueue { 
public: 
    void push(const std::string& str, size_t notify_size, size_t max_size); 
    std::string pop(); 

private: 
    std::queue<std::string> queue; 
    boost::mutex mutex; 
    boost::condition_variable cond; 
}; 

void ConcurrentQueue::push(
    const std::string& str, size_t notify_size, size_t max_size) { 
    size_t queue_size; 
    {{ 
     boost::mutex::scoped_lock lock(mutex); 
     if (queue.size() < max_size) { 
      queue.push(str); 
     } 
     queue_size = queue.size(); 
    }} 
    if (queue_size >= notify_size) 
     cond.notify_one(); 
} 

std::string ConcurrentQueue::pop() { 
    boost::mutex::scoped_lock lock(mutex); 
    while (!queue.size()) 
     cond.wait(lock); 
    std::string str = queue.front(); 
    queue.pop(); 
    return str; 
} 

这些线程使用下面的队列来处理和使用libcurl发送。

boost::shared_ptr<ConcurrentQueue> queue_a(new ConcurrentQueue); 
boost::shared_ptr<ConcurrentQueue> queue_b(new ConcurrentQueue); 

void prod_run(size_t iterations) { 
    try { 
     // stagger startup 
     boost::this_thread::sleep(
       boost::posix_time::seconds(random_num(0, 25))); 
     size_t save_frequency = random_num(41, 97); 
     for (size_t i = 0; i < iterations; i++) { 
      // compute 
      size_t v = 1; 
      for (size_t j = 2; j < (i % 7890) + 4567; j++) { 
       v *= j; 
       v = std::max(v % 39484, v % 85783); 
      } 
      // save 
      if (i % save_frequency == 0) { 
       std::string iv = 
           boost::str(boost::format("%1%=%2%") % i % v); 
       queue_a->push(iv, 1, 200); 
      } 
      sleep_frame(); 
     } 
    } catch (boost::thread_interrupted&) { 
    } 
} 

void prodcons_run() { 
    try { 
     for (;;) { 
      std::string iv = queue_a->pop(); 
      queue_b->push(iv, 1, 200); 
     } 
    } catch (boost::thread_interrupted&) { 
    } 
} 

void cons_run() { 
    try { 
     for (;;) { 
      std::string iv = queue_b->pop(); 
      send_http_post("http://127.0.0.1", iv); 
     } 
    } catch (boost::thread_interrupted&) { 
    } 
} 

我对这种方式使用互斥的理解不应该使系统无响应。如果有的话,我的应用程序将陷入僵局并永远睡眠。

有没有办法让其中的200个同时创建一个场景,但情况并非如此?

更新:

当我重新启动电脑,大部分我需要重新插拔的USB键盘的时间让它作出回应。鉴于司机的评论,我认为这可能是相关的。我尝试更新北桥驱动程序,尽管它们是最新的。我会看看是否有其他需要关注的驱动程序。

更新:

我看过的内存,非分页池,CPU,处理,港口和他们都不是在在系统响应在任何时间以惊人的速度。最后可能会出现尖峰,尽管这对我来说是不可见的。

更新:

当系统挂起,它停止渲染和不键盘响应。它呈现的最后一帧虽然保持不变。系统听起来像仍在运行,当系统恢复时,事件查看器中没有任何内容说它崩溃了。没有故障转储文件。我解释这是因为操作系统被阻止执行。

+0

“奇怪的是,它在安全模式下的窗户中工作正常” - 这表明某些第三方驱动程序正在搞砸。可能是防病毒或防火墙。您可以尝试卸载这些类型的包,以查看事后突然开始工作。 – 2013-02-18 18:37:41

+0

你看过内存使用情况了吗?如果应用程序使用大量内存,则可能会发现系统无响应。以安全模式运行将减少系统的负载。但我同意,AV或防火墙似乎是一个可能的候选人 - 尤其是AV。 AV软件将涉及很多事情,并且通常可能会使系统无法响应,只需通过“所有事情都必须经过这个狭窄的空洞”类型的行为。 – 2013-02-18 18:49:02

+0

@MichaelBurr根据驱动程序更新了评论。我会试着看看下面的内容。谢谢你的评论! – 2013-02-18 18:54:35

回答

1

互斥锁锁定其他使用相同锁的应用程序。操作系统使用的任何互斥锁都不应该(直接)适用于任何应用程序。

当然,如果互斥体是以某种方式使用操作系统实现的,那么它可能会调用操作系统,从而使用CPU资源。但是,互斥锁不应该导致比使用CPU资源的应用程序更糟糕的行为。

当然,如果以不恰当的方式使用锁定,则应用程序的不同部分会死锁,因为函数1获取锁定A,然后函数2获取锁定B.如果功能1尝试获取锁定B,并且函数2试图在释放它们各自的锁之前获取锁A,则会产生死锁。这里的诀窍是始终以相同的顺序获取多个锁。因此,如果您同时需要两把锁,请始终首先获取锁A,然后锁定B.

Deadlockin不应该对操作系统造成影响 - 如果有的话,它会使它更好,但如果应用程序在某种情况下出现死锁,那么通过调用操作系统可能会导致问题 - 例如如果锁定是通过以下方式完成的:

while (!trylock(lock)) 
{ 
     /// do nothing here 
} 

它可能会导致系统使用高峰。

+0

但特别是如果应用程序发生死锁(即所有线程都进入停止状态),操作系统永远不会无响应。除非Windows调度器比我想象的更糟糕,但这又会与它在安全模式下工作的方面相冲突。 – 2013-02-18 18:39:58

+0

完全同意。 – 2013-02-18 18:46:52

+0

我想知道为什么你包含关于死锁的段落呢?我可能忽略了一些重要的东西,但是... – 2013-02-18 18:54:38

相关问题