C 递增变量';s值与多线程

C 递增变量';s值与多线程,c,multithreading,variables,C,Multithreading,Variables,我试着用两个线程编写一个代码,它应该将2个数字x 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

我试着用两个线程编写一个代码,它应该将2个数字x 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;
}
#包括
#包括
#包括
void*inc\u x(void*x\u void\u ptr){
int*x_ptr=(int*)x_void_ptr;

而(+(+*x_ptr)没有发生同步。特别是,您没有
pthread_join()
线程

这意味着,当您试图打印结果时,线程很可能甚至没有运行。它们可能已经运行,但您无法确定

另外,请参见上面@mch的评论:您实际上根本没有增加计数器,以添加到上一个计数器中。因此,即使线程确实运行了,结果也不会是您想要的结果

为了正确操作,通常,您应该向条件变量发送信号(并在使用线程上等待它)确保结果已准备就绪,或在访问结果之前加入线程。发送条件变量的信号重量较轻,因此这是您希望对重复任务执行的操作,而不是生成/加入数千个线程

(在某些情况下,可以使用原子操作成功地在线程之间共享数据,但对于线程初学者来说,这太高级了。这太容易让您的生活非常不愉快,现在请使用cond vars。)

通常,您还希望确保程序退出时没有“遗忘”线程仍在运行,这是调用
pthread\u join
的另一个好理由,即使您对同步不感兴趣,否则

您可能倾向于认为这没什么大不了的,因为程序无论如何都会退出,有时甚至是真的。但一般来说,这种假设是无效的。例如,您很可能在正在写入的文件或半写入的文件中存在垃圾,因为线程在操作过程中突然被终止。

或者,当操作系统突然从其脚下抽出仍在访问的内存页时,您可能出现工作线程segfault。这“看起来”完全正常,除非它没有。没有发生同步。特别是,您没有
pthread\u join()
线程

这意味着,当您试图打印结果时,线程很可能甚至没有运行。它们可能已经运行,但您无法确定

另外,请参见上面@mch的评论:您实际上根本没有增加计数器,以添加到上一个计数器中。因此,即使线程确实运行了,结果也不会是您想要的结果

为了正确操作,通常,您应该向条件变量发送信号(并在使用线程上等待它)确保结果已准备就绪,或在访问结果之前加入线程。发送条件变量的信号重量较轻,因此这是您希望对重复任务执行的操作,而不是生成/加入数千个线程

(在某些情况下,可以使用原子操作成功地在线程之间共享数据,但对于线程初学者来说,这太高级了。这太容易让您的生活非常不愉快,现在请使用cond vars。)

您通常还希望确保程序退出时没有“遗忘”线程仍在运行,这是调用
pthread\u join
的另一个很好的理由,即使您对同步不太感兴趣

您可能倾向于认为这没什么大不了的,因为程序无论如何都会退出,有时甚至是真的。但一般来说,这种假设是无效的。例如,您很可能在正在写入的文件或半写入的文件中存在垃圾,因为线程在操作过程中突然被终止。

或者,当操作系统突然从其脚下抽出仍在访问的内存页时,您可能出现工作线程故障。这“看起来”完全正常,除非它不正常。

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

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

在递增时在两个函数中都这样使用:(*y_ptr)+

void*inc\u y(void*y\u void\u ptr){
int*y_ptr=(int*)y_void_ptr;

而(+(+*y_ptr)在检查x和y的反射值之前,主要使用以下内容:

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

在递增时在两个函数中都这样使用:(*y_ptr)+

void*inc\u y(void*y\u void\u ptr){
int*y_ptr=(int*)y_void_ptr;

(++)(*y_ptr)
*x_ptr++
增加指针。你也不用等待线程。你怎么知道它们没有增加?这是一个多线程程序,你不知道主线程中的
printf(“%d,%d”,x,y)
是否会在线程之前或之后执行。如果你修复了指针的增加(参见mch)。您在一次循环迭代中增加两次值。
*x_ptr++;
增加指针。您也不等待线程。您如何知道它们没有增加?这是一个多线程程序,您不知道
printf(“%d,%d”,x,y)是否
in main将在线程之前或之后执行。如果修复指针增量(请参见mch),则在一次循环迭代中将该值增加两次