另一个线程安全队列实现

Another thread safe queue implementation

本文关键字:实现 队列 安全 线程 另一个      更新时间:2023-10-16

我有一个 Queue的类,我试图使线程安全。它具有这三个成员变量:

    std::queue<T>   m_queue;
    pthread_mutex_t m_mutex;
    pthread_cond_t  m_condition;

和一个推动和弹出式实现为:

    template<class T> void Queue<T>::push(T value)
    {
        pthread_mutex_lock( &m_mutex );
        m_queue.push(value);
        if( !m_queue.empty() )
        {
            pthread_cond_signal( &m_condition );
        }
        pthread_mutex_unlock( &m_mutex );
    }
    template<class T> bool Queue<T>::pop(T& value, bool block)
    {
        bool rtn = false;
        pthread_mutex_lock( &m_mutex );
        if( block )
        {
            while( m_queue.empty() )
            {
                pthread_cond_wait( &m_condition, &m_mutex );
            }
        }
        if( !m_queue.empty() )
        {
            value = m_queue.front();
            m_queue.pop();  
            rtn = true;
        }
        pthread_mutex_unlock( &m_mutex );
        return rtn;
    }

不幸的是,偶尔出现的问题可能是该代码的错。也就是说,有两个线程,有时线程1永远不会从 push()出来,而其他时候线程2则永远不会从 pop()出来( block参数为 true),尽管队列不是空的。

我了解还有其他可用的实现,但是如果需要,我想尝试修复此代码。有人看到任何问题吗?

构造函数具有适当的初始化:

    Queue()
    {
        pthread_mutex_init( &m_mutex, NULL );
        pthread_cond_init( &m_condition, NULL );
    }

和destructor,相应的"销毁"呼叫。

如保罗·鲁贝尔(Paul Rubel)所述,您需要首先初始化静音。在这一点上,将MUTEX包装在可以处理您的初始化和最终确定的班级中可能是个好主意。例如:

class mutex {
private:
    mutex(const mutex &m);
    mutex &operator=(const mutex &m);
    // OR inherit from boost::noncopyable
public:
    mutex() {
        pthread_mutex_init(&mut_, nullptr);
    }
    ~mutex() {
        pthread_mutex_destroy(&mut_);
    }
    pthread_mutex_t get() const { return mut_; }
private:
    pthread_mutex_t mut_;
};

note是boost.threading库,其中包含写得很好的同步类。

您必须在使用之前初始化互斥x:pthread_mutex_init

//somewhere before push/pop
pthread_mutex_init(&m_mutex)

这完全与您的问题无关,但是您可以修复推送功能:

template<class T> void Queue<T>::push(T value)
{
    pthread_mutex_lock( &m_mutex );
    if( m_queue.empty() )
    {
        m_queue.push(value);
        pthread_cond_signal( &m_condition );
    }
    else
    {
        m_queue.push(value);
    }
    pthread_mutex_unlock( &m_mutex );
}

我意识到测试ARM构建时发生的问题。解决方案是更新Pthreads库。随着更新的pthreads,一切都可以正常运行。