为什么这个线程安全队列会造成死锁?

nsi*_*akr 0 c++ multithreading stl pthreads

我已经编写了自己的线程安全队列版本.但是,当我运行此程序时,它会挂起/死锁.

想知道,为什么这会永远锁定/挂起.

void concurrentqueue::addtoQueue(const int number)
{
    locker currentlock(lock_for_queue);
    numberlist.push(number);
    pthread_cond_signal(&queue_availability_condition);
}

int concurrentqueue::getFromQueue()
{
    int number = 0;


    locker currentlock(lock_for_queue);
    if ( empty() )
    {
        pthread_cond_wait(&queue_availability_condition,&lock_for_queue);
    }

    number = numberlist.front();
    numberlist.pop();
    return number;
}

bool concurrentqueue::empty()
{       
    return numberlist.empty();
}
Run Code Online (Sandbox Code Playgroud)

我写过,班级储物柜是RAII.

class locker
{
public:
    locker(pthread_mutex_t& lockee): target(lockee)
    {
        pthread_mutex_lock(&target);
    }
    ~locker()
    {
        pthread_mutex_unlock(&target);
    }
private:
        pthread_mutex_t target;
};
Run Code Online (Sandbox Code Playgroud)

我的编剧/读者线程代码非常简单.Writer线程,添加到队列和读取器线程,从队列中读取.

void * writeintoqueue(void* myqueue)
{
    void *t = 0;
    concurrentqueue *localqueue = (concurrentqueue *) myqueue;

    for ( int i = 0; i < 10 ; ++i)
    {
        localqueue->addtoQueue(i*10);
    }

    pthread_exit(t);
}

void * readfromqueue(void* myqueue)
{
    void *t = 0;
    concurrentqueue *localqueue = (concurrentqueue *) myqueue;
    int number = 0;
    for ( int i = 0 ; i < 10 ; ++i)
    {
        number = localqueue->getFromQueue();
        std::cout << "The number from the queue is " << number << std::endl;
    }
    pthread_exit(t);
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ork 5

这绝对不安全:

if ( empty() ) 
{ 
    pthread_cond_wait(&queue_availability_condition,&lock_for_queue); 
} 
Run Code Online (Sandbox Code Playgroud)

如果以前没有等待呼叫另一个线程getFromQueue()addtoQueue()已经暗示条件变量和退出,但等待的线程获得性锁之前,则该线程可能会退出,并期望队列有它的价值.您必须重新检查队列是否为空.

将if更改为while:

while ( empty() ) 
{ 
    pthread_cond_wait(&queue_availability_condition,&lock_for_queue); 
} 
Run Code Online (Sandbox Code Playgroud)