【问题标题】:Implementing an thread-safe queue with pThreads: Deadlock?使用 pThreads 实现线程安全队列:死锁?
【发布时间】:2013-07-24 06:40:51
【问题描述】:

我正在尝试实现基于固定数组的线程安全队列。队列包含一个 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;
}

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

【问题讨论】:

  • 请不要写这样的代码......说清楚,int *ptr1 = (int*)malloc(sizeof(int)); *int = 5; queue_put(q, ptr1); 所有那些丑陋的不必要的类型转换最终会让你发疯。
  • 谢谢,好点子!我想你的意思是*ptr1=5; 对吧?
  • 是的,对不起,我会更正评论(编辑:似乎它不会让我)

标签: c thread-safety pthreads deadlock


【解决方案1】:

我相信问题在于queue_get。您在互斥锁解锁之前返回。尝试将返回值存储到临时变量中,解锁互斥体,然后返回值。

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

【讨论】:

    【解决方案2】:

    您在解锁 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;
    

    【讨论】:

      【解决方案3】:

      您需要将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);
      

      注意缺少所需的演员表)

      【讨论】:

        猜你喜欢
        • 2017-06-14
        • 2010-12-10
        • 2012-05-30
        • 1970-01-01
        • 2023-03-18
        • 1970-01-01
        • 2014-02-28
        • 1970-01-01
        • 2021-08-30
        相关资源
        最近更新 更多