2012-12-19 81 views
1

我有一個類,Queue,我試圖讓線程安全。它有三個成員變量:另一個線程安全隊列實現

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

和push和pop實現爲:

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

和析構函數,相應的 '破壞' 電話。

+0

你正在像'gdb'這樣的調試器中運行它嗎? 'push()'或'pop()'在中間拋出異常/崩潰? – Anthony

+0

不好意思說,但是你的代碼不包含任何錯誤......而且寫得很好......嘗試用gdb進行調試,但問題不在於你在找的地方 – benjarobin

+2

小修正:在push函數中if (!m_queue.empty())'始終爲真 – benjarobin

回答

0

我意識到測試的ARM構建時發生的問題。解決方案是更新pthreads庫。隨着更新的pthreads,一切運行良好。

0

您必須在使用前初始化互斥鎖:pthread_mutex_init

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

感謝您的幫助,雖然我已經這麼做了。我只是沒有完成我應該在我的職位。 – jensph

1

正如保羅·魯貝爾提到的,你需要先初始化互斥。在這一點上,可能是一個好主意,將一個類中的互斥包裝起來,以處理您的初始化和最終化。例如:

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圖書館,其中包含很好寫的同步類。

+2

另外[std :: mutex](http://en.cppreference.com/w/cpp/thread/mutex)類,如果你有幸使用符合C++ 11標準的工具鏈,線程支持庫](http://en.cppreference.com/w/cpp/thread)。 – WhozCraig

+0

@WhozCraig如果我們都能夠如此幸運! – Anthony

+1

@ anthony-arnold:對於你的班級,你應該刪除複製構造函數和賦值操作符,否則你違反了三條規則。 – GManNickG

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); 
} 
+0

或者只是'if(m_queue.empty())pthread_cond_signal(&m_condition); m_queue.push(value);'因爲這全部在鎖內,所以在推送值之前發信號是可以的。 –

+0

看起來我可以把'if(m_queue.empty())'完全取出來。謝謝。 – jensph