【问题标题】:Multiple threads are not working simultaneously on Ubuntu in C多个线程在 C 中的 Ubuntu 上不能同时工作
【发布时间】:2017-06-20 04:16:16
【问题描述】:

我使用multi-threading 编写了一个代码,它创建了两个threads

  • Consumer Thread:到dequeue 来自Circular Queue 的一个元素。
  • Producer Thread:转至enqueueCircular Queue中的十个元素。

Consumer Thread 在插入六个元素之前处于等待状态,并且仅在 Producer Threadqueue 中插入六个元素之后才有效,即 dequeue 元素。以下是我的代码:

void *producer(void *t)
{
  int i;
  long my_id = (long)t;
  for (i=0; i<10; i++) 
  {
    pthread_mutex_lock(&count_mutex);
    printf("\nInserting value = %d ",count);
    enQueue(count);
    displayQueue();
    count++;
    if (count == 6)
    {
      pthread_cond_signal(&count_threshold_cv);
      printf("\nproducer: thread %ld, count = %d  Threshold reached.\n",my_id, count);
    }
    printf("\nproducer: thread %ld, count = %d, unlocking mutex\n",my_id, count);
    pthread_mutex_unlock(&count_mutex);
  }
  pthread_exit(NULL);
}

void *consumer(void *t)
{
  long my_id = (long)t;
  printf("Starting Consumer Thread(): thread %ld\n", my_id);
  pthread_mutex_lock(&count_mutex);
  while (count<6) 
  {
    pthread_cond_wait(&count_threshold_cv, &count_mutex);
    printf("\nconsumer: thread %ld Condition signal received.\n", my_id);
  }
  printf(" \nDeleted value =%d ",deQueue());
  displayQueue();
  printf("\nconsumer: thread %ld count now = %d.\n", my_id, count);
  pthread_mutex_unlock(&count_mutex);
  pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
  int i, rc;
  long t1=1, t2=2;
  pthread_t threads[2];
  //Threads Created

  pthread_create(&threads[1], &attr, consumer, (void *)t1);
  pthread_create(&threads[0], &attr, producer, (void *)t2);

 //Thread Clean Up Followed
}

代码在Windows(CodeBlocks) 中按预期工作。

  • 0-5 先插入队列
  • 在插入 6 时,达到阈值并从 queue 中删除一个元素。
  • 在此之后,queue 中插入了 6-9。

但是在Ubuntu 中执行时,首先插入0-9 个元素,然后从queue 中删除一个元素。 用于在ubuntu 中编译的命令:g++ -pthread name.cpp。 这种不同行为的原因是什么以及如何解决这个问题? 完整代码Follow link

【问题讨论】:

  • 这里的代码太多了。这可以简化为minimal reproducible example
  • 我已经添加了整个程序,以便检查整个功能。它是一个没有错误的程序。虽然主要功能仅在ProducerConsumer函数中实现,但由于问题在 ubuntu 中执行,我添加了整个代码,以便可以在 ubuntu 中检查和执行它。现在,为了您的方便,我删除了额外的代码。
  • 现在它不是一个工作示例...您必须再次添加一些或代码,以便我们可以重现问题
  • @koleygr 我添加了整个代码的链接Here。在你自己的 IDE 中试试这个。
  • 恕我直言,这是 C.

标签: c multithreading ubuntu


【解决方案1】:

这种不同行为的原因是什么

线程并不能保证两个不同线程中的事情会以任何特定的顺序发生,除非您明确同步它们以便它们这样做。你不同步,所以事情以某种顺序发生,然后它们以不同的顺序发生。这完全在意料之中。

如果您希望事情完全按照某种顺序发生,您要么必须明确地让两个线程相互等待,要么不使用线程。

正如您现在的代码一样,没有什么可以阻止“生产者”循环 10 次然后退出。

【讨论】:

  • 有些东西可以防止producer 循环10 次:count==6 时的信号命令。它向消费者线程发出信号以恢复由wait 语句暂停的功能。这在 Windows 中也可以正常工作。在 Windows 中,当 count==6 消费者线程执行到 dequeue 一个元素时。但在 Ubuntu 中,消费者线程最后出列,即在生产者终止之后。
  • @HimanshuJindal 您假设您的消费者线程在生产者线程插入任何项目之前执行pthread_cond_wait(&amp;count_threshold_cv, &amp;count_mutex); - 但您的代码中没有任何内容可以防止这种情况发生 - 所以您很可能会看到行为上的差异2 种不同的操作系统。另请注意,printf("\nInserting value = %d ",count); 会欺骗您,如果您在终端中运行程序,您将不会立即看到该输出。在末尾添加 \n。
  • @HimanshuJindal 调用pthread_cond_signal 不会停止调用线程。它会唤醒pthread_cond_wait 中的线程,但是没有任何地方可以说明这会阻止调用者继续运行。并且没有说明消费者应该何时开始运行。
  • 事实上,我什至看不到任何东西可以保证消费者线程甚至在生产者排队并退出之前已经开始运行任何代码。
  • 要获得你想要的行为,你需要 2 个条件变量。 2. 生产者插入6个元素后需要等待条件变量,消费者通过该条件消费完所有6个元素后需要再次唤醒生产者
【解决方案2】:

有些情况会在您的代码中产生死锁。例如,如果“消费者”线程在“生产者”线程之前启动,则会产生死锁情况。 “消费者”正在等待发出“count_threshold_cv”信号,并且它已经获得了“count_mutex”互斥锁。 '生产者'等待获取'count_mutex'的平均时间。所以这种死锁情况会导致应用程序挂起。请设计应用程序以避免这种情况。我们不能保证哪个线程先启动。专门获取互斥锁应该只针对需要的代码段集。

编辑:由于 'pthread_cond_wait' 传递 'count_mutex' 这不会产生死锁。但是由于我们不能保证线程执行的顺序,所以行为是不可预测的。 此外,您不能依赖 cout 输出。由于输出可能不符合执行顺序。

【讨论】:

  • 如果此时消费者线程发生死锁,生产者将不会执行。但是线程在死锁之后也正在工作。这意味着当我们发出wait 命令时,mutex 在等待时间内被解锁。我也在一些文档上阅读了相同的内容。另外不要忘记代码在 Windows 上正常工作。
  • 如果“消费者”先启动,死锁可能不会发生。所以根据情况......它可能在windows上运行。
  • 不明白你的意思。我在 windows 和 ubuntu 中都执行了相同的代码。在 ubuntu 中执行时我没有修改任何内容。
  • 艺人的回复解释了更多。
  • @Pra 这不是死锁。当您执行 pthread_cond_wait 时,互斥锁被解锁(并在 pthread_cond_wait 返回之前再次锁定)
猜你喜欢
  • 1970-01-01
  • 2021-04-19
  • 1970-01-01
  • 2019-06-18
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
  • 2022-06-17
  • 1970-01-01
相关资源
最近更新 更多