【问题标题】:C pthread: Multiple Threads but only ONE thread is usedC pthread:多线程但只使用一个线程
【发布时间】:2016-04-05 21:06:53
【问题描述】:

我正在研究生产者和消费者问题。我创建了一个生产者将内容放入有界缓冲区并使用多个消费者从缓冲区获取数据。为了检查每个消费者是否都在工作,我给他们每个人一个 ID,然后让他们打印出来。

以下是创建多个消费者的代码。

#define CONSUMER_NUM 5;
pthread_t consumer[CONSUMER_NUM];
for(i=0;i<CONSUMER_NUM;i++){
    int t = i;
    pthread_create(&consumer[i],NULL,fun_consumer,(void*)&t);   
}   // pass i to the function fun_consumer to be an id of the thread

我的预期可能是这样的:

Consumer 1
Consumer 2
Consumer 3
Consumer 4
Consumer 5

我知道由于线程的随机执行,输出通常不会像这样。我在这里期望的是大多数消费者会开始工作。然而,事实是打印出来的程序是这样的:

Consumer 5
Consumer 5
Consumer 5
Consumer 5
Consumer 5

这里只使用了一个消费者。我尝试了“睡眠”,它可以给我预期的输出,但会导致执行缓慢。我想知道是否有更好的方法来解决这个问题?

【问题讨论】:

    标签: c multithreading pthreads


    【解决方案1】:

    你给每个线程一个指向局部变量i的指针。随着每次循环迭代i 发生变化 - 到线程实际启动并完成就绪循环时,i 等于 5(最后一个值)。

    但是,这只是众多潜在结果之一。实际上,您的线程 id 可以读取任何内容,因为您在这段代码中有一个经典的数据竞争。您正在从多个线程访问一个变量,该变量不受任何保护。如果运气好的话,甚至可以读到 42。

    解决方案。 为每个线程动态创建一个新变量并传递该变量的地址(您需要在线程中删除以防止内存泄漏),或者将整数变量转换为指针并将该值提供给线程。要做到这一点(有点)便携,你的i实际上应该是uintptr_t类型,而不是unsigned int

    如何每次创建新变量的示例:

    for (i=0 ; i<CONSUMER_NUM; ++i) {
        int* id = malloc(sizeof(int));
        *id = i;
        pthread_create(&consumer[i],NULL,fun_consumer, id);   
    }
    ...
    void* fun_consumer(void* arg) {
        int id = *(int*)(arg);
        free(arg)
        // rest of code
    

    【讨论】:

    • 谢谢!我尝试了第一种方法并更改了代码(如上所示,我已对其进行了编辑),但仍然输出所有 5...
    • @IvyLin,你没听懂我说的。您仍然提供不断变化的变量的地址。请用代码查看我的更新答案。
    • 我明白了!感谢您的耐心,它现在可以工作了:) @SergeyA
    【解决方案2】:

    你给他们一个变量i的引用,它会在循环中改变。它执行得如此之快,以至于每个线程都将其视为 5。

    您仍然收到五个线程,您只是发送错误的号码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-26
      • 1970-01-01
      • 2018-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多