为什么这个线程安全队列,创建死锁? [英] Why this thread safe queue, creates a deadlock?

查看:179
本文介绍了为什么这个线程安全队列,创建死锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了我自己的线程安全队列的版本。但是,当我运行这个程序时,它会挂起/死锁本身。

I've written my own version of thread safe queue. However, when I run this program, it hangs/deadlocks itself.

想知道为什么这个锁会永久挂起。

Wondering, why is this locks/hangs forever.

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

我写了类寄存器为RAII。

I've written, the class locker as 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;
};

我的写入器/读取器线程代码非常简单。

My writer/reader thread code is very simple. Writer thread, adds to the queue and reader thread, reads from the queue.

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


推荐答案

将spong的评论重新制作为答案: locker 类不应该通过值复制 pthread_mutex_t 。您应该使用引用或指针,例如:

Reformulating spong's comment as an answer: your locker class should NOT be copying the pthread_mutex_t by value. You should use a reference or a pointer instead, e.g.:

class locker
{
public:
    locker(pthread_mutex_t& lockee): target(lockee)
    {
        pthread_mutex_lock(&target);
    }
    ~locker()
    {
        pthread_mutex_unlock(&target);
    }
private:
        pthread_mutex_t& target;  // <-- this is a reference
};

这样做的原因是所有的pthreads数据类型应该被当作不透明类型 - 知道他们是什么,不应该复制它们。库执行类似于查看特定内存地址以确定是否保持锁的事情,所以如果有两个副本的变量指示是否保持锁,奇怪的事情可能发生,如多个线程似乎成功锁定相同的互斥。

The reason for this is that all pthreads data types should be treated as opaque types -- you don't know what's in them and should not copy them. The library does things like looking at a particular memory address to determine if a lock is held, so if there are two copies of a variable that indicates if the lock is held, odd things could happen, such as multiple threads appearing to succeed in locking the same mutex.

我测试了你的代码,它也为我锁了。然后,我通过 Valgrind 运行它,虽然它没有在这种情况下死锁(由于不同的时间,或者可能Valgrind只模拟一个线程一次),Valgrind报告许多错误。在修复 locker 后使用引用,它运行时没有死锁,并且不会在Valgrind中生成任何错误。

I tested your code, and it also deadlocked for me. I then ran it through Valgrind, and although it did not deadlock in that case (due to different timings, or maybe Valgrind only simulates one thread at a time), Valgrind reported numerous errors. After fixing locker to use a reference instead, it ran without deadlocking and without generating any errors in Valgrind.

请参阅还可以使用pthread调试

这篇关于为什么这个线程安全队列,创建死锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆