2013-08-20 85 views
2

在下面的代码中,我创建了一个具有循环的线程,当我调用条件时它将执行完整的迭代。但是,如果我调用1000次,则invoking_thread值与main末尾的exec_thread不同。发生了什么,我该如何解决这个问题?我不想退出运行threadfunc的线程,因为我可能需要将其用于进一步操作。进一步说明为什么调用线程数比在C程序中执行线程数多?

#include < pthread.h> 
#include < stdio.h> 

pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
int invoking_thread = 0, exec_thread = 0; 
pthread_t pth; 

void *threadfunc(void *parm) 
{ 
    int x; 
    for (;;) { 
     pthread_mutex_lock(&mutex); 
     pthread_cond_wait(&cond, &mutex); 
     //printf("Inside the thread %d\n", ins); 
     exec_thread++; 
     pthread_mutex_unlock(&mutex); 
    } 
    return NULL; 
} 


void create_thread() { 
    pthread_create(&pth,NULL,threadfunc,"foo"); 
} 

int main(int argc, char **argv) 
{ 
    create_thread(); 
    int y = 0; 
    while (1) { 
     if (y == 1000) { 
      break; 
     } 
     y++; 
     invoking_thread++; 
     printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 
     pthread_cond_signal(&cond); 
     pthread_mutex_lock(&mutex); 
     pthread_mutex_unlock(&mutex); 
    } 
    printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 
    printf("Main completed\n"); 
    return 0; 
} 

细节: 我可以告诉你我的整个情况:1000大小的数组与0值进行初始化。 1线程以无限循环启动。对于1000次迭代,我将信号传递给线程以增加数组中每个元素的值。传递信号后,这些值在循环中乘以2。在下一步中,再次将1000个信号传递给线程以增加数组中每个元素的值。然后,与之前相同,所有元素值在循环中都乘以2。然后打印结果。

现在,添加一些块,大部分时间我得到分段错误。剩下的时间我没有得到期望的价值。

#include < pthread.h> 

    #include < stdio.h> 

    pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

    int invoking_thread = 0, exec_thread = 0, signal_count = 0; 

    pthread_t pth; 

    int res[1000]; 

void *threadfunc(void *parm) { 

for (;;) { 

    pthread_mutex_lock(&mutex); 

    while (signal_count == 0) 
     pthread_cond_wait(&cond, &mutex); 

    signal_count--; // consume a signal 

//printf("Inside the thread res[%d]++\n", exec_thread); 

    exec_thread++; 

res[exec_thread]++; 

    pthread_mutex_unlock(&mutex); 

    } 

    return NULL; 

    } 


    void create_thread() { 

     pthread_create(&pth,NULL,threadfunc,"foo"); 

    } 


    int main(int argc, char **argv) 
    { 

create_thread(); 

int y; 

for (y = 0;y<1000;y++) { 
    res[y] = 0; 
} 
y = 0; 
while (1) { 
    if (y == 1000) { 
     break; 
    } 
    y++; 
    invoking_thread++; 
    //printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 
    pthread_mutex_lock(&mutex); 
     signal_count++; 
     pthread_mutex_unlock(&mutex); 
     pthread_cond_signal(&cond); 
} 
printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 

for (y = 0;y<1000;y++) { 
    res[y] = res[y]*2; 
} 
exec_thread = 0; 
y = 0; 
while (1) { 
    if (y == 1000) { 
     break; 
    } 
    y++; 
    invoking_thread++; 
    //printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 
    pthread_mutex_lock(&mutex); 
     signal_count++; 
     pthread_mutex_unlock(&mutex); 
     pthread_cond_signal(&cond); 
} 
printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 

for (y = 0;y<1000;y++) { 
    res[y] = res[y]*2; 
} 

// result 
for (y = 0;y<1000;y++) { 
    printf("%d result for %d\n",res[y], y); 
} 

printf("Main completed\n"); 
return 0; 
    } 

因此,我的问题是,线程调用应该有后前1000点的信号,它是不是在等待等待,然后让代码做计算,那么它应该被允许做进一步的1000所调用。等等以获得期望的结果。希望我能够解释我的情况。

回答

2

pthread_cond_signal()将唤醒任何线程等待条件如果有一个线程等待。如果没有,那么这个电话将什么也不做。这很可能是你的情况。有几个后续调用pthread_cond_signal(),而工作线程实际上并没有睡觉。

要确保一次调用一个工人通行证,您将不得不使用两个pthread_cond_t--一个表示工人的起始,另一个表示通知工作已结束。另一个是忙着等待,直到1000个工作完成。这是修改的代码:

int main(int argc, char **argv) 
{ 
    create_thread(); 
    int y = 0; 
    int executed = 0; 
    while (executed <1000) { 
     invoking_thread++; 
     printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 
     pthread_mutex_lock(&mutex); 
     executed = exec_thread; // read inside mutex to ensure variable visibility 
     pthread_cond_signal(&cond); 
     pthread_mutex_unlock(&mutex); 
    } 
    printf("Count: Invoked %d and Inside : %d\n", invoking_thread, exec_thread); 
    printf("Main completed\n"); 
    return 0; 
} 
+0

我刚刚编译了程序并确认这是问题所在。主线程像一个门口的公牛一样运行 - 发送1000个信号,但另一个线程在主线程退出之前从来没有机会收到它们。如果你在主线程中进行睡眠,那么另一个线程将接收信号。 –

+0

感谢您的关注。但是加入睡眠和延迟并不会帮助我达到这个速度。有什么方法可以让我获得信号,让所有1000人完成。这将帮助我在此之后添加检查 –

+0

@Vishwadeep最简单的事情就是在主服务器中忙于等待(并保持信号),但线程实际上已完成1000次工作。 – Dariusz

0

您是否忘记在主体中添加pthread_join()以等待所有线程完成计算?

[See here]

+0

使用pthread_join()将等待整个线程完成。我不想完成该线程。线程应该保持活动状态,以便我可以进一步添加更多代码。 –

+0

但如果您的主线程在所有线程完成之前退出,那么您如何获得相同的计算次数? – nommyravian

+0

线程无限期地工作。这不是问题。 – Dariusz

1

条件变量是无状态的。您期望条件变量具有“信号”状态。它不是。如果你想把状态和条件变量联系起来,你必须这样做。你可以有一个“signal_count”变量,然后做到这一点:

void *threadfunc(void *parm) 
{ 
    int x; 
    for (;;) { 
     pthread_mutex_lock(&mutex); 
     while (signal_count == 0) 
      pthread_cond_wait(&cond, &mutex); 
     signal_count--; // consume a signal 
     //printf("Inside the thread %d\n", ins); 
     exec_thread++; 
     pthread_mutex_unlock(&mutex); 
    } 
    return NULL; 
} 

同理:

pthread_mutex_lock(&mutex); 
    signal_count++; 
    pthread_mutex_unlock(&mutex); 
    pthread_cond_signal(&cond); 

注意,互斥体保护的状态,你必须实现的状态,你不能调用pthread_cond_wait除非你知道你需要等待,并且当pthread_cond_wait返回时,你不能认为该状态有任何特殊的值。这就是你如何使用条件变量。

+0

谢谢戴维,我试着使用信号计数。我仍然无法获得相同的号码。还有一件事,如果我删除了重复的打印语句,那么调用和执行之间的区别就越来越大。 –

+0

请告诉我,如果我明白错误。使用条件变量我不能依赖执行的次数。我找到了使用单独变量来收集计数的方法,就像显示为signal_count一样。 –

+0

@Vishwadeep发布无法使用的代码。很可能你还有其他一些bug。我不确定你的意思是“取决于执行次数”。我想说的是,你不能指望一个条件变量改变状态(比如说“信号”和“无信号”),因为它没有状态。另外,你必须记住'pthread_cond_wait'不是一个有条件的等待,它是*条件的一个无条件等待。 –

相关问题