1

我有一堂课,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 );
    }

和析构函数,相应的“销毁”调用。

4

4 回答 4

1

正如 Paul Rubel 所提到的,您需要先初始化互斥锁。在这一点上,将互斥锁包装在一个将为您处理初始化和终结的类中可能是一个好主意。例如:

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_;
};

值得注意的是Boost.Threading库,其中包含编写得非常好的同步类。

于 2012-12-19T22:46:32.907 回答
0

这根本与您的问题无关,但您可以修复推送功能:

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 );
}
于 2012-12-19T23:27:30.697 回答
0

我意识到在为 ARM 测试构建时出现了问题。解决方案是更新 pthreads 库。使用更新的 pthreads,一切运行良好。

于 2013-01-07T16:00:26.413 回答
0

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

//somewhere before push/pop
pthread_mutex_init(&m_mutex)
于 2012-12-19T22:34:51.927 回答