【问题标题】:Segmentation fault using pthreads使用 pthread 的分段错误
【发布时间】:2016-11-11 18:04:31
【问题描述】:

我正在编写一个程序来测试我对条件变量的理解。基本上,线程 0 检查 count 是否为偶数,如果是,则增加它。如果不是,那么它会向线程 1 发出信号,该线程 1 会增加 count 变量。该过程一直持续到计数达到 15。这是我的代码:

#include <pthread.h>
#include <stdio.h>
#define numThreads 2

int count=0;
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;


void *checkEven(void *threadId)
{   while(count<=15){
//lock the mutex
pthread_mutex_lock(&count_mutex);
printf("even_thread: thread_id=%d  count=%d\n",threadId,count); 
if(count%2==0){
count++;
}
else{
printf("Odd count found, signalling to odd thread\n");
pthread_cond_signal(&count_threshold_cv);
}
pthread_mutex_unlock(&count_mutex);
sleep(1);
}
}

void *checkOdd(void *threadId)
{
pthread_mutex_lock(&count_mutex);   //obtain a lock
while(count<=15){
pthread_cond_wait(&count_threshold_cv, &count_mutex);   //wait() relinquishes the lock 
count++;
printf("odd_thread: thread_id=%d, count=%d\n",threadId,count);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}

int main()
{ 
pthread_t threads[numThreads];
int rc;
int a=0;
int b=0;
pthread_create(&threads[0], NULL, checkEven, (void *)a);
pthread_create(&threads[1], NULL, checkEven, (void *)b);
pthread_join(0,NULL);
pthread_join(1,NULL);
pthread_exit(NULL);
}

有人能告诉我为什么会出现分段错误(核心转储)错误吗?我知道当一个进程试图违反其他进程的地址空间时会发生此错误,但除此之外没有其他内容。有人可以帮忙吗?谢谢!

【问题讨论】:

  • 问题是,一旦计数为奇数,偶数线程就会调用信号。因此,奇数线程获得锁并在 wait() 调用后继续,并增加计数。然后解锁,偶数线程获得锁,循环继续。
  • 你没有正确初始化你的pthread_mutex_tpthread_cond_t
  • 我认为这不是它所面临问题的原因。实际上,我通过传递 0 而不是threads[0],弄乱了对join() 的调用。
  • 我从未说过这是您观察到的行为的原因。我只是指出您的代码在这方面是不正确的。
  • 感谢@EOF。你能告诉我它有什么问题吗?即使从我开始,我也一直像这样初始化它们。我什么时候错了?

标签: c linux pthreads


【解决方案1】:

您将零作为要加入的线程传递给pthread_join

pthread_join(0,NULL);

你想要的:

pthread_join(threads[0],NULL);
pthread_join(threads[1],NULL);

不过,您还有其他几个错误。一方面,您的 checkOdd 代码会调用 pthread_cond_wait,即使轮到该线程时也是如此。

您似乎不了解条件变量。具体来说,您似乎认为条件变量会以某种方式知道您正在等待的事情是否已经发生。它没有——条件变量是无状态的。跟踪您正在等待的内容以及它是否已经发生是您的工作。

【讨论】:

  • 但是当偶数线程发出信号时,它不是在wait()之后继续吗?
  • @PrashantPandey 是的,但是只有在轮到偶数线程时,偶数线程才会发出信号。如果你在已经轮到你的时候等待,你将永远等待。
  • 条件变量不知道该轮到哪个线程了。如果你调用pthread_cond_wait,它会等待,不管它是否应该等待。所以不要打电话给pthread_cond_wait,除非你 100% 确定你想等待,只有在轮不到你的时候才能等待。但你不检查。
  • 好的。所以,你是在建议我先检查一个条件,如果不成立,再调用wait(),不是吗?
  • 标准模式是:while (this_thread_needs_to_wait) pthread_cond_wait(...);。如何检查线程是否需要等待取决于您。您确实需要 while 循环,因为 pthread_cond_wait 不能保证它只在轮到您时返回,因为它不知道何时轮到或不轮到您。条件变量是无状态的。
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 2011-10-26
  • 2018-10-03
  • 2016-11-05
  • 2015-01-08
  • 2016-04-22
  • 1970-01-01
相关资源
最近更新 更多