c++ - 并发队列内存消耗爆炸,然后程序崩溃

标签 c++ multithreading boost queue

这是一个使用VS 2010并发队列的典型生产者/消费者模式,问题是当我运行程序时,内存消耗超过1GB然后程序崩溃,有人可以指出这段代码中的问题吗?

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> 
#include <ctime> 

#include <boost\shared_ptr.hpp>
#include <boost\thread.hpp>
#include <concurrent_queue.h>



void wait2(int milliseconds)
{
    boost::this_thread::sleep(boost::posix_time::milliseconds(milliseconds)); 
}

class CQueue
{
    Concurrency::concurrent_queue<int>  Q;

    boost::mutex                m;
    boost::condition_variable   cv;

public:

    CQueue():QValue(-1)
    {
    }

    int QRead()
    {
        while(Q.empty())
        {
            boost::unique_lock<boost::mutex> lk(m);
            cv.wait(lk);
        }

        int res;
        if(Q.try_pop(res))
        {
            QValue = res;
            return true;
        }
        return false;
    }

    void QWrite(int i)
    {
        Q.push(i);
        cv.notify_one();
    }

    int QValue;
};

CQueue myqueue;

void write()
{
    int i = 0;
    while(true)
    {
        myqueue.QWrite(++i);
    }
}


void read()
{
    while(true)
    {
        if( myqueue.QRead())
            std::cout << myqueue.QValue << std::endl;
        else
            std::cout << "failed to read" << std::endl;
    }
}
void main ()
{

    boost::thread w(write);
    boost::thread r(read);

    w.join();
    r.join();

}

最佳答案

我在简单的双核上使用 VS'13 和 Boost 1.52 构建并测试了您的代码。

正如已经说过的,由于您的生产者-消费者设计没有定义当库存(并发队列)达到给定水平时阻止生产者的阈值,因此生产者在队列中推送了太多数据,因此内存不足增加,窗口开始交换,卡住,如果超过最大提交大小,进程可能会崩溃,等等......

请注意,提交大小限制取决于多个因素,编译器、编译器选项、程序运行的操作系统,...

因此,在下面我添加了一种方法,如果队列大小达到阈值,则阻止生产者,如果队列大小低于阈值,则消费者唤醒生产者。

通过这些更改,我们添加了一些同步,这可以限制一点并行性,但使用中的内存受到控制。

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> 
#include <ctime> 

#include "..\..\..\boost\boost\shared_ptr.hpp"
#include "..\..\..\boost\boost\thread.hpp"

#include <concurrent_queue.h>

#define STOCK_THRESHOLD 1000

void wait2(int milliseconds)
{
    boost::this_thread::sleep(boost::posix_time::milliseconds(milliseconds)); 
}

class CQueue
{
    Concurrency::concurrent_queue<int>  Q;

    boost::mutex                consumerMutex;
    boost::condition_variable   consumerCV;

    boost::mutex                producerMutex;
    boost::condition_variable   producerCV;

public:

    CQueue():QValue(-1)
    {
    }

    int QRead()
    {
        while(Q.empty())
        {
            boost::unique_lock<boost::mutex> lk(consumerMutex);
            consumerCV.wait(lk);
        }

        int res;
        if(Q.try_pop(res))
        {
            QValue = res;
            if(Q.unsafe_size() <= STOCK_THRESHOLD)
            {
                producerCV.notify_one();
            }
            return true;
        }
        return false;
    }

    void QWrite(int i)
    {
        while(Q.unsafe_size() > STOCK_THRESHOLD){
            boost::unique_lock<boost::mutex> lk(producerMutex);
            producerCV.wait_for(lk, boost::chrono::milliseconds(10));
        }
        Q.push(i);
        consumerCV.notify_one();
    }

    int QValue;
};

CQueue myqueue;

void write()
{
    int i = 0;
    while(true)
    {
        myqueue.QWrite(++i);

    }
}


void read()
{
    while(true)
    {
        if( myqueue.QRead())
            std::cout << myqueue.QValue << std::endl;
        else
            std::cout << "failed to read" << std::endl;
    }
}

void main ()
{

    boost::thread w(write);
    boost::thread r(read);

    w.join();
    r.join();

}

关于c++ - 并发队列内存消耗爆炸,然后程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17802428/

相关文章:

python - 在 Boost Python 中公开模板化基类的最佳方式?

c++ - FFMPEG(C++)从缓冲区转换和压缩单个图像

java - 使用多线程对文件进行排序

c++ - 在 Qt 中收集线程

c++ - 使用 Boost 库程序选项的必需和可选参数

c++ - 获取当前保存的 std::variant 的 typeid(如 boost::variant type())

c++ - 如何删除一次制作的所有纹理?

c++ - 除以零不会抛出 SIGFPE

带有 typedef 多参数的 C++ 模板?

java - 将图像转换为灰度图像时应用程序没有响应