0

我正在学习 C 线程概念,并在下面编写了简单的代码。现在,当我编译并运行它时,我会得到随机行为,就像它意外打印一样。

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

void * func_threadName(void * i) {

    int *x=(int *)i;
    printf("I'm thread : %d\n",*x);

return NULL;
}
main()
{
    int iter;
    printf("testing multithreading....\n");

    pthread_t thread_arr[3];

    for (iter=0;iter<3;iter++)
    {
        pthread_create(&thread_arr[iter],NULL,func_threadName,&iter);

    }

     for (iter=0;iter<3;iter++)
     {
         pthread_join(thread_arr[iter],NULL);
     }
}

它无法预测地打印如下:

diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o 
testing multithreading....
I'm thread : 0
I'm thread : 0
I'm thread : 0
diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o 
testing multithreading....
I'm thread : 0
I'm thread : 2
I'm thread : 1
diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o 
testing multithreading....
I'm thread : 2
I'm thread : 2
I'm thread : 0

但是当我在创建线程后进行如下轻微更改时,它可以完美运行并按顺序打印。

pthread_create(&thread_arr[iter],NULL,func_threadName,&iter);
        sleep(1);

现在每次的输出都是这样的:

diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o 
testing multithreading....
I'm thread : 0
I'm thread : 1
I'm thread : 2
diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o 
testing multithreading....
I'm thread : 0
I'm thread : 1
I'm thread : 2
diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o 
testing multithreading....
I'm thread : 0
I'm thread : 1
I'm thread : 2

我想了解在第一种情况下,是否显示了不可预测的行为,因为所有线程共享相同的内存空间,因此在一个线程终止之前,另一个线程使用相同的 i 值?欢迎提供任何其他信息。

4

3 回答 3

5

您无法准确判断线程何时运行,因此主线程可能会继续,从而更改其循环中的计数器。由于该循环计数器是一个指针,所有线程都有相同的指针指向完全​​相同的变量。您还可以在第二个循环中使用相同的变量,因此可以在线程的生命周期内对其进行两次修改。

“按原样”传递数字会更好(尽管更“hackish”):

pthread_create(&thread_arr[iter], NULL, func_threadName, (void *) iter);

然后在线程函数中得到它像这样:

int x = (int) i;
于 2013-06-01T08:07:10.263 回答
1

每个线程都应该看到一个不同的int对象,因此您必须使用第二个数组来管理它。

void * func_threadName(void * i) {

    int *x= i;
    printf("I'm thread : %d\n",*x);

    return NULL;
}

int main(void) {
  printf("testing multithreading....\n");

  pthread_t thread_arr[3];
  int iter_id[3];

  for (int iter=0; iter<3; iter++) {
    iter_id[iter] = iter;
    pthread_create(&thread_arr[iter], NULL, func_threadName, &iter_id[iter]);
  }

  for (iter=0;iter<3;iter++) {
    pthread_join(thread_arr[iter],NULL);
  }
}

同样在C

  • void*将 a分配给另一个数据指针时,您不必强制转换
  • 所有函数,甚至main必须用返回类型声明
  • 应该声明和定义一个不接收参数的函数(void)
于 2013-06-01T20:38:15.877 回答
0

代码的问题是您传递变量的地址而不是值。因此,所有线程都引用该地址存储的“相同”值。这意味着,正如 Joachim 所提到的,该值的变化可能不够快,以至于新创建的线程无法获取它。当使用“睡眠”时,主线程允许处理器执行其他指令,因此在创建新线程之前更改迭代变量的值。总而言之,您需要传递变量的值而不是 Joachim 示例中的地址。

于 2013-10-19T15:24:43.693 回答