用pThreads实现一个线程安全的队列:死锁?

时间:2013-07-24 16:38:03

标签: c thread-safety pthreads deadlock

我正在尝试基于固定数组实现线程安全队列。该队列包含一个void指针数组。

pthread_t a;
pthread_t b;
Queue *q;

Queue* queue_new(int size)
{
    // malloc stuff
}

void queue_put(Queue* q, void* item)
{
    pthread_mutex_lock(&(q->lock));
    // details on array queue managment
    pthread_mutex_unlock(&(q->lock));
}

void* queue_get(Queue* q)
{
    pthread_mutex_lock(&(q->lock));
    // more details ...
    return q->queue[old_front];
    pthread_mutex_unlock(&(q->lock));
}


void *func_a (void *ptr)
{
    void *ptr1 = malloc(sizeof(int));
    *((int*)ptr1) = 5;
    queue_put(q, ptr1);

    void *ptr2 = malloc(sizeof(int));
    *((int*)ptr2) = 4;
    queue_put(q, ptr2);
    return NULL;
}

void *func_b (void *ptr)
{
    void *ptr3 = malloc(sizeof(int));
    *((int*)ptr3) = 7;
    queue_put(q, ptr3);

    queue_get(q); // critical part !

    return NULL;
}


int main ()
{
    q = queue_new(3);
    pthread_create(&a, NULL, func_a, NULL);
    pthread_create(&b, NULL, func_b, NULL);
    pthread_join(a, NULL);
    pthread_join(b, NULL);

    queue_print(q);

    return 0;
}

我认为这是一种非常简单的方法。不幸的是,程序冻结了。但是,当我删除queue_get(q);中的func_b时,它的工作正常。我认为这必定是某种僵局。有任何想法吗? Queue的非线程安全版本已经过测试,工作正常。为清晰起见,隐藏了代码。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我认为问题出在queue_get之内。您在互斥锁解锁之前返回。尝试将返回值存储到一个temprary变量中,解锁互斥锁,然后返回值。

void* queue_get(Queue* q)
{
    void* temp;
    pthread_mutex_lock(&(q->lock));
    // more details ...
    temp = q->queue[old_front];
    pthread_mutex_unlock(&(q->lock));
    return temp;
}

答案 1 :(得分:1)

在解锁queue_get中的互斥锁之前,您正在返回:

return q->queue[old_front];
pthread_mutex_unlock(&(q->lock));

这应该是:

void *retValue = q->queue[old_front];
pthread_mutex_unlock(&(q->lock));
return retValue;

答案 2 :(得分:1)

您希望将queue_get中的解锁线移到return之上,因为现在它永远不会到达。所以锁从未被释放。

pthread_mutex_unlock(&(q->lock));
return q->queue[old_front];

或者,你可能想要什么,以避免在锁外触摸它:

void * ret = q->queue[old_front];
pthread_mutex_unlock(&(q->lock));
return ret;

(从更具风格的观点来看:你的价值分配会更加“清洁”:

int * ptr1 = malloc(sizeof(*ptr1));
*ptr1 = 5;
queue_put(q, ptr1);

注意缺少演员阵容)