c++ - 线程安全队列有问题吗?

标签 c++ multithreading concurrency queue pthreads

我正在尝试使用 C++ 中的 pthreads 编写一个线程安全的队列。我的程序在 93% 的时间里都能正常工作。另外 7% 的时间它会吐垃圾,或者似乎睡着了。我想知道我的队列中是否存在上下文切换会破坏它的缺陷?

// thread-safe queue
// inspired by http://msmvps.com/blogs/vandooren/archive/2007/01/05/creating-a-thread-safe-producer-consumer-queue-in-c-without-using-locks.aspx
// only works with one producer and one consumer
#include <pthread.h>
#include <exception>

template<class T>
class tsqueue
{
    private:
        volatile int m_ReadIndex, m_WriteIndex;
        volatile T *m_Data;
        volatile bool m_Done;
        const int m_Size;
        pthread_mutex_t m_ReadMutex, m_WriteMutex;
        pthread_cond_t m_ReadCond, m_WriteCond;
    public:
        tsqueue(const int &size);
        ~tsqueue();
        void push(const T &elem);
        T pop();
        void terminate();
        bool isDone() const;
};

template <class T>
tsqueue<T>::tsqueue(const int &size) : m_ReadIndex(0), m_WriteIndex(0), m_Size(size), m_Done(false) {
    m_Data = new T[size];
    pthread_mutex_init(&m_ReadMutex, NULL);
    pthread_mutex_init(&m_WriteMutex, NULL);
    pthread_cond_init(&m_WriteCond, NULL);
    pthread_cond_init(&m_WriteCond, NULL);
}

template <class T>
tsqueue<T>::~tsqueue() {
    delete[] m_Data;
    pthread_mutex_destroy(&m_ReadMutex);
    pthread_mutex_destroy(&m_WriteMutex);
    pthread_cond_destroy(&m_ReadCond);
    pthread_cond_destroy(&m_WriteCond);
}


template <class T>
void tsqueue<T>::push(const T &elem) {
    int next = (m_WriteIndex + 1) % m_Size;
    if(next == m_ReadIndex) {
        pthread_mutex_lock(&m_WriteMutex);
        pthread_cond_wait(&m_WriteCond, &m_WriteMutex);
        pthread_mutex_unlock(&m_WriteMutex);
    }
    m_Data[m_WriteIndex] = elem;
    m_WriteIndex = next;
    pthread_cond_signal(&m_ReadCond);
}

template <class T>
T tsqueue<T>::pop() {
    if(m_ReadIndex == m_WriteIndex) {
        pthread_mutex_lock(&m_ReadMutex);
        pthread_cond_wait(&m_ReadCond, &m_ReadMutex);
        pthread_mutex_unlock(&m_ReadMutex);
        if(m_Done && m_ReadIndex == m_WriteIndex) throw "queue empty and terminated";
    }
    int next = (m_ReadIndex +1) % m_Size;
    T elem = m_Data[m_ReadIndex];
    m_ReadIndex = next;
    pthread_cond_signal(&m_WriteCond);
    return elem;
}

template <class T>
void tsqueue<T>::terminate() {
    m_Done = true;
    pthread_cond_signal(&m_ReadCond);
}

template <class T>
bool tsqueue<T>::isDone() const {
    return (m_Done && m_ReadIndex == m_WriteIndex);
}

可以这样使用:

// thread 1
while(cin.get(c)) {
    queue1.push(c);
}
queue1.terminate();


// thread 2
while(!queue1.isDone()) {
    try{ c = queue1.pop(); }
    catch(char const* str){break;}
    cout.put(c);
}

如果有人发现这有问题,请说:)

最佳答案

是的,这里肯定有问题。您对队列成员变量的所有访问都发生在互斥体之外。事实上,我不完全确定您的互斥体在保护什么,因为它们只是在等待条件变量。

此外,您的阅读器和编写器似乎总是步调一致地操作,绝不允许队列的大小超过一个元素。

关于c++ - 线程安全队列有问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/539824/

相关文章:

python - 如何抽象调用这个具体 Thread 类的方式?

c# - 带有自定义 TaskScheduler 的 Parallel.ForEach 以防止 OutOfMemoryException

python - 在 Python 中序列化 Sqlite3

c++ - `cudaEventDestroy` 异步启动返回错误码时如何正确响应?

c++ - MPI忽略cin

c - 解锁时向多个线程发出信号的一把锁

vb.net - 当预期为 true 时,InvokeRequired 不断返回 false

concurrency - 可以对并发代码进行静态检查吗?

c++ - 我将如何搜索这个包含任何剩余船只数组的文件?

c++ - 在字符串中添加逗号