簡體   English   中英

使用 pthreads 創建線程安全隊列是否正確?

[英]is it correct way to create a thread safe queue using pthreads?

最近開始學習多線程,所以有些東西還是不太明白。 我試圖寫一個線程安全的隊列,但我懷疑我是否做對了。 由於我沒有注意到我的錯誤,如果您向我指出錯誤,我會很高興。 謝謝你的回復,還有。 我不確定我是否在此代碼中正確使用了條件變量。

template<class T>
class SafeQueue {
private:
    std:: queue<T> _data;
    pthread_mutex_t _mutex;
    pthread_cond_t _condition;
public:
    SafeQueue();
    ~SafeQueue();
    void push(const T &x);
    T front();
    T back();
    void pop();
    int size();
    bool empty();
};

template<class T>
SafeQueue<T>::SafeQueue(){
    pthread_mutex_init(&_mutex, NULL);
    pthread_cond_init(&_condition, NULL);
}

template<class T>
SafeQueue<T>::~SafeQueue(){
    pthread_mutex_destroy(&_mutex);
    pthread_cond_destroy(&_condition);
}

template<class T>
void SafeQueue<T>::push(const T &x){
    pthread_mutex_lock(&_mutex);
    _data.push(x);
    pthread_cond_signal(&_condition);
    pthread_mutex_unlock(&_mutex);
}

template<class T>
T SafeQueue<T>::front(){
    pthread_mutex_lock(&_mutex);
    if(_data.empty() && _data.size() == 0){
        pthread_mutex_unlock(&_mutex);
        throw SafeQueueException("Queue is empty");
    }
    if(_data.empty()){
        pthread_cond_wait(&_condition, &_mutex);
    }
    T temp = _data.front();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

template<class T>
T SafeQueue<T>::back(){
    pthread_mutex_lock(&_mutex);
    if(_data.empty() && _data.size() == 0){
        pthread_mutex_unlock(&_mutex);
        throw SafeQueueException("Queue is empty");
    }
    if(_data.empty()){
        pthread_cond_wait(&_condition, &_mutex);
    }
    T temp = _data.back();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

template<class T>
void SafeQueue<T>::pop(){
    pthread_mutex_lock(&_mutex);
    if(_data.empty() && _data.size() == 0){
        pthread_mutex_unlock(&_mutex);
        throw SafeQueueException("Queue is empty");
    }
    if(_data.empty()){
        pthread_cond_wait(&_condition, &_mutex);
    }
    _data.pop();
    pthread_mutex_unlock(&_mutex);
}

template<class T>
int SafeQueue<T>::size(){
    pthread_mutex_lock(&_mutex);
    int temp = _data.size();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

template<class T>
bool SafeQueue<T>::empty(){
    pthread_mutex_lock(&_mutex);
    bool temp = _data.empty();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

代碼中的一些點我不太明白為什么你把_data.empty() && _data.size() == 0這樣的東西? 當您只能使用其中一個時。 而且也不需要鎖定大小和空方法,因為它們只是讀取變量並返回它們,它們不會修改任何東西。

順便提一句。

確實有些人認為如果他們將互斥鎖放在開始和結束操作中是一些數據結構(在你的情況下是隊列),那么他們認為它現在是線程安全的,但它不是真的。

例如,假設您的隊列有一個元素。

q = 1

然后你有一些這樣的代碼:

if (!q.empty()) {
  auto element = q.back();
  q.pop();
}

在這個例子中,兩個線程將執行這段代碼檢查,他們會注意到隊列不為空,然后他們將在內部 go 條件和一個線程首先取回元素,然后運氣好,同一個線程將彈出元素。 在那之后,線程 2 將取回元素,因為線程 1 彈出元素並且現在隊列為空,然后線程 2 返回方法失敗並出現異常,因此如果隊列條件不為空,則進入線程 2 則失敗。 所以這個隊列不是線程安全的

很高興看到你正在擴展你的技能。 如果您使用的是 C++,那么 C++11 之后的標准庫中有線程。 我建議您改用這些功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM