如果足够多的活动,boost::mutex 可以锁定操作系统吗?

Posted

技术标签:

【中文标题】如果足够多的活动,boost::mutex 可以锁定操作系统吗?【英文标题】:Can boost::mutex lock out an OS if enough are active? 【发布时间】:2013-02-18 18:29:48 【问题描述】:

我正在处理一个中间处理线程的生产者消费者问题。当我运行 200 个这样的应用程序时,它会在大量连接超时时将系统锁定在 win7 中。不幸的是,不是以我知道如何调试它的方式。系统变得无响应,我必须使用电源按钮重新启动它。它在我的 mac 上运行良好,奇怪的是,它在安全模式下的 windows 下运行良好。

我使用的是 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、句柄、端口,在系统响应时,它们都没有处于惊人的速度。可能最后会出现一些尖峰,尽管我看不到。

更新:

当系统挂起时,它会停止渲染并且不响应键盘。它渲染的最后一帧仍然存在。系统听起来它仍在运行,当系统恢复运行时,事件查看器中没有任何内容表明它崩溃了。也没有故障转储文件。我将此解释为操作系统被阻止执行。

【问题讨论】:

“奇怪的是,它在安全模式下的 Windows 中运行良好”——这表明某些 3rd 方驱动程序正在搞砸。可能是防病毒软件或防火墙。您可以尝试卸载这些类型的软件包,看看之后是否会突然开始工作。 您查看过内存使用情况吗?如果应用程序使用大量内存,您可能会发现系统无响应。在安全模式下运行将减少系统的负载。但我同意,AV 或防火墙似乎是一个可能的候选者——尤其是 AV。反病毒软件会与很多东西挂钩,并且通常会通过“所有东西都必须通过这个狭窄的洞”类型的行为来使系统无响应。 @MichaelBurr 根据驱动程序更新了评论。接下来我会尝试看看。感谢 cmets! @MatsPetersson 根据指标更新评论。我不确定是否还有其他需要检查的地方。 您能否澄清一下:是您的应用程序挂起/断开连接,还是操作系统本身? 【参考方案1】:

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

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

当然,如果你以不恰当的方式使用锁,应用程序的不同部分就会陷入死锁,因为函数 1 获取锁 A,然后函数 2 获取锁 B。如果函数 1 尝试获取锁 B ,而函数 2 在释放各自的锁之前尝试获取锁 A,则您遇到了死锁。这里的技巧是始终以相同的顺序获取多个锁。所以如果同时需要两把锁,总是先获取锁A,再获取锁B。

死锁不应该像这样影响操作系统 - 如果有的话,它会使它变得更好,但是如果应用程序在死锁的情况下以某种方式“行为不端”,它可能会通过大量调用操作系统而导致问题 - 例如,如果锁定由:

while (!trylock(lock))

      /// do nothing here

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

【讨论】:

但特别是如果应用程序死锁(即所有线程进入停止状态),操作系统永远不会无响应。除非 Windows 调度程序比我想象的更糟糕,但这又会与它在安全模式下工作的方面发生冲突。 我想知道你为什么要包含关于死锁的段落?我可能会在这里忽略一些重要的事情,但是……

以上是关于如果足够多的活动,boost::mutex 可以锁定操作系统吗?的主要内容,如果未能解决你的问题,请参考以下文章

CUDA主机代码的互斥锁? boost::mutex 由于使用 nvcc 重新定义了 BOOST_COMPILER 没有解决方案

boost::interprocess_mutex 与进程本地 boost::mutex

C++ 多线程 读锁之后不能跟写锁 shared_lock之后不能跟unique_lock 死锁 解决方案

boost::mutex::scoped_lock

/include/boost/thread/pthread/mutex.hpp:111: boost::mutex::~mutex(): Assertion `!res' 失败

boost mutex 应用