2016-11-02 37 views
1

我试着编写一个带有2个线程的代码,它应该将2个数字y增加到100,每次发生增量时,都应该打印出来。使用多线程递增变量的值

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

void *inc_x(void *x_void_ptr){ 
    int *x_ptr = (int *)x_void_ptr; 
    while (++(*x_ptr)<100) { 
     printf("x increment to %d \n",*x_ptr); 
     *x_ptr++; 
    } 
    return NULL; 

} 

void *inc_y(void *y_void_ptr){ 
    int *y_ptr = (int *)y_void_ptr; 
    while (++(*y_ptr)<100) { 
     printf("y increment to %d \n",*y_ptr); 
     *y_ptr++; 
    } 
    return NULL; 
} 

int main() 
{ 
    int x = 0; 
    int y = 0; 
    printf("x: 0 , y : 0\n"); 
    pthread_t inc_x_thread, inc_y_thread; 
    if (pthread_create(&inc_x_thread, NULL, inc_x, &x)) { 
     fprintf(stderr, "Error creating thread \n"); 
     return 1; 
    } 
    if (pthread_create(&inc_y_thread, NULL, inc_y, &y)) { 
     fprintf(stderr, "Error creating thread \n"); 
     return 2; 
    } 
    printf("%d , %d" , x,y); 

    return 0; 
} 

但我的x,y值没有增加。有人能告诉我为什么吗?谢谢(顺便说一句,我是C新手)。

+6

'* x_ptr ++;'增加指针。你也不要等待线程。 – mch

+3

你怎么知道他们不增加?它是一个多线程程序,你不能知道'mainf中的printf(“%d,%d”,x,y);'会在线程之前还是之后执行。 – Lundin

+0

如果你修复指针增量(见mch)。你在一次循环迭代中增加值两次 –

回答

5

没有同步发生。特别是,你没有pthread_join()的线程。

这意味着什么意思是说,当你试图打印出结果时,线程甚至都没有运行。他们可能跑了,但你无法确定。

此外,请参阅上面的@mch评论:您确实没有递增计数器,以添加到以前。所以即使线程确实运行了,结果也不会是你想要的。

对于正确的操作,一般来说,您应该发出一个条件变量(并在消耗线程上等待)以确保结果已准备好,或者在访问结果之前连接线程。发信号通知一个条件变量的重量较轻,所以这就是你想要做的重复任务,而不是产卵/连接数千个线程。 (在某些情况下,可以在线程之间成功地共享数据,使用原子操作,但对于初学者来说,线程过于先进,太容易让你的生活相当不高兴,因此现在就使用cond vars。 )

您通常会希望确保没有“遗忘”的线程仍在运行时程序退出,这是另一个很好的理由骂pthread_join,即使你是不是在同步太大的兴趣,否则。

您可能会倾向于认为它并不重要,因为程序退出,有时甚至是这样。但总的来说,这个假设是无效的。你可以例如非常好的文件被写入或半写入文件,因为线程在操作中突然中断。
或者你可能有一个工作线程段错误,而操作系统突然拉开它仍然从脚下访问的内存页面。其中“看起来”完全正常,除非没有。

+0

另外,主函数应该调用'pthread_exit()' – Aif

1

使用在主以下之前检查x和y的反射值:

pthread_join(inc_x_thread, NULL); 
    pthread_join(inc_y_thread, NULL); 

和在两种功能

使用像这样同时增加:(* y_ptr)++;

void *inc_y(void *y_void_ptr){ 
    int *y_ptr = (int *)y_void_ptr; 
    while (++(*y_ptr)<100) { 
    printf("y increment to %d \n",*y_ptr); 
    (*y_ptr)++; // correction here 
    } 
    return NULL; 
    }