繁体   English   中英

C ++中的线程安全队列

[英]Thread Safe queue in C++

这是在C ++中创建可以处理二进制数据的无符号char *数组线程安全队列的正确方法吗?

请注意,数据是从主线程而不是创建的pthread生成的,这使我怀疑pthread_mutex_t是否在推入和弹出操作中可以正确地工作。

线程安全队列

#include <queue>
#include <pthread.h>

class ts_queue
{

private:

    std::queue<unsigned char*> _queue_;
    pthread_mutex_t mutex;
    pthread_cond_t cond;

public:

    ts_queue()
    {
        pthread_mutex_init(&mutex, NULL);
        pthread_cond_init(&cond, NULL);
    }

    void push(unsigned char* data)
    {
        pthread_mutex_lock(&mutex);

        _queue_.push(data);

        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }

    void pop(unsigned char** popped_data)
    {
        pthread_mutex_lock(&mutex);

        while (_queue_.empty() == true)
        {
            pthread_cond_wait(&cond, &mutex);
        }

        *popped_data = _queue_.front();
        _queue_.pop();

        pthread_mutex_unlock(&mutex);
    }
};

消费者测试:

void *consumer_thread(void *arguments)
{
    ts_queue *tsq = static_cast<ts_queue*>(arguments);

    while (true)
    {
        unsigned char* data = NULL;

        tsq->pop(&data);

        if (data != NULL)
        {
            // Eureka! Received from the other thread!!!
            // Delete it so memory keeps free.
            // NOTE: In the real scenario for which I need
            // this class, the data received are bitmap pixels
            // and at this point it would be processed
            delete[] data;
        }
    }

    return 0;
}

生产者测试:

void main()
{
    ts_queue tsq;

    // Create the consumer
    pthread_t consumer;
    pthread_create(&consumer, NULL, consumer_thread, &tsq));

    // Start producing
    while(true)
    {
        // Push data. 
        // Expected behaviour: memory should never run out, as the
        // consumer should receive the data and delete it.
        // NOTE: test_data in the real purpose scenario for which I 
        // need this class would hold bitmap pixels, so it's meant to 
        // hold binary data and not a string

        unsigned char* test_data = new unsigned char [8192];
        tsq.push(test_data);
    }

    return 0;
}

您如何知道消费者永远不会获取数据? 当我尝试您的程序时,出现了段错误,GDB告诉我使用者确实得到了一个指针,但这是无效的。

我相信您的问题是_queue_成员上存在数据争用。 push()调用_queue_.push(data) (上写_queue_ )同时举行push_mutexpop()调用_queue_.front()在读_queue_ )和_queue_.pop()上一次写_queue_ )同时举行pop_mutex ,但是push()pop()可以同时发生,导致两个线程同时写入(和读取) _queue_ ,这是经典的数据争用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM