我不明白为什么我的 pthread 会冻结

I can't understand why does my pthread freeze

我试图创建一个线程安全队列,但出了点问题。我不明白为什么我的线程会冻结。 预期:1 2 3,但我什么也没得到(一切都冻结了)

我猜问题是在前面(pop)和get(peek)方法中误用了条件变量,但我找不到我的错误。 能否请您指出我的错误并解释错误是什么?

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();
    bool peek(T &x);
    bool get(T &x);
};

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_mutex_unlock(&_mutex);
}

template<class T>
T SafeQueue<T>::front(){
    pthread_mutex_lock(&_mutex);
    T temp;
    while(!get(temp)){
        pthread_cond_wait(&_condition, &_mutex);
    }
    pthread_mutex_unlock(&_mutex);
    return temp;
}

template<class T>
bool SafeQueue<T>::get(T &x){
    bool result = false;
    pthread_mutex_lock(&_mutex);
    if(!_data.empty()){
        result = true;
        x = _data.front();
        pthread_cond_signal(&_condition);
    }
    pthread_mutex_unlock(&_mutex);
    return result;
}

template<class T>
void SafeQueue<T>::pop(){
    pthread_mutex_lock(&_mutex);
    T temp;
    while(!peek(temp)){
        pthread_cond_wait(&_condition, &_mutex);
    }
    pthread_mutex_unlock(&_mutex);
}

template<class T>
bool SafeQueue<T>::peek(T &x){
    bool result = false;
    pthread_mutex_lock(&_mutex);
    if(!_data.empty()){
        result = true;
        x = _data.front();
        _data.pop();
        pthread_cond_signal(&_condition);
    }
    pthread_mutex_unlock(&_mutex);
    return result;
}

main.cpp

int main(){
    SafeQueue<int> q;
    q.push(1);
    q.push(2);
    q.push(3);
    cout << q.front() << endl; q.pop();
    cout << q.front() << endl; q.pop();
    cout << q.front() << endl; q.pop();

    return 0;
}

这是你的 front :

template<class T>
T SafeQueue<T>::front(){
    pthread_mutex_lock(&_mutex);
    T temp;
    while(!get(temp)){
        pthread_cond_wait(&_condition, &_mutex);
    }
    pthread_mutex_unlock(&_mutex);
    return temp;
}

它锁定互斥锁,做一些事情,释放互斥锁。作为“某些东西”的一部分,它调用 get(temp).

您的 get 是:

template<class T>
bool SafeQueue<T>::get(T &x){
    bool result = false;
    pthread_mutex_lock(&_mutex);
    if(!_data.empty()){
        result = true;
        x = _data.front();
        pthread_cond_signal(&_condition);
    }
    pthread_mutex_unlock(&_mutex);
    return result;
}

它试图锁定互斥量....

来自docs

If the mutex is already locked, the calling thread shall block until the mutex becomes available.

互斥锁永远不会可用,因为它在调用者 (front) 中被锁定并且只有在 get return 时才会被释放,但是 get从不 return.

避免这种死锁的一种方法是使用执行实际工作但不使用互斥体的私有方法。仅在 public 方法中锁定互斥量。然后你只需要确保永远不要从另一个 public 方法调用 public 方法。或者使用递归互斥锁。

无论如何,我建议您使用 std::thread 及其亲戚(std::mutex 和其他)。

如果我没记错的话,你在 Front() 函数中锁定了互斥量,然后在其中调用了 get(temp) ,它试图再次锁定,这应该是不可能的。