如果变量i直接传递给此代码中的线程会发生什么?

时间:2013-10-03 11:54:00

标签: c multithreading

#include <pthread.h>
#include <stdio.h>
#include <math.h>
#include <stdio.h>
#include <pthread.h>
#define NO_OF_THREADS 5

void print_function(int* i)
{
 int count;
 for(count=0; count<10; count++)
  printf("Hello world from thread %d\n",*i);
 pthread_exit(NULL);
}

int main()
{
 pthread_t printThreads[NO_OF_THREADS];
 int thread_no[NO_OF_THREADS];
 int i;

 for(i=0; i<NO_OF_THREADS; i++)
 {
  thread_no[i] = i;
  pthread_create(&printThreads[i], NULL, print_function,&thread_no[i]);
 }

 int j;
 for(j=0;j<NO_OF_THREADS;j++)
  pthread_join(printThreads[j],NULL);
 puts("Main over and out");
 return 0;
}

不直接将计数器变量i的地址作为参数传递 对于pthread_create函数,它首先被分配给一个未使用的数组插槽 然后将数组元素的地址作为参数传递。这个完成了 避免在父线程和创建的线程之间访问i的竞争条件。 解释如果变量i直接传递给线程会发生什么。

4 个答案:

答案 0 :(得分:1)

变量可以“直接”传递而没有风险,只要它成功地与void *进行转换,当然。如果使用该方法,则不需要每线程缓冲。

传递单个位置的地址imain()地址),其内容随着更多线程的创建而变化,当然是疯狂的。

答案 1 :(得分:0)

你可以直接传递它没有问题,你必须把它强制转换为整数,因为它的类型是pthread_create中的void *

答案 2 :(得分:0)

thread_no[]的目的是什么?你想在任何地方改变它吗?如果不是(并且正如我在这里看到的那样),那么不用担心任何竞争条件,因为你将不同的thread_no[i]传递给不同的线程,并且在产生传递它的线程之前设置它的值。因此,在thread_no[i]线程生成之前,不会传递或访问i。只需通过thread_no[i]而不是&thread_no[i]或只是通过i(因为它是相同的)。

答案 3 :(得分:0)

如果将i的地址传递给pthread_create()调用中的每个线程,则无法保证每个线程在变量中看到的值。可能是线程0将看到诸如2或3之类的值,因为即使i在调用pthread_create()时为0,在线程运行并读取变量时,值也是已经被主线改变了。

例如,使用这个经过温和修改的代码版本,我得到的输出是:

Hello world from thread 3
Hello world from thread 4
Hello world from thread 4
Hello world from thread 3
Hello world from thread 5
Hello world from thread 5
Hello world from thread 5
...
Hello world from thread 5
Hello world from thread 5
Hello world from thread 5
Main over and out

修改后的代码:

删除<math.h>并重复<stdio.h><pthread.h>;删除了thread_no变量;修复了线程函数的类型以匹配pthread_create()期望的等等。

#include <pthread.h>
#include <stdio.h>
#define NO_OF_THREADS 5

void *print_function(void *ip);
void *print_function(void *ip)
{
    int *i = ip;
    int count;
    for(count=0; count<10; count++)
        printf("Hello world from thread %d\n",*i);
    pthread_exit(NULL);
    return 0;
}

int main(void)
{
    pthread_t printThreads[NO_OF_THREADS];
    int i;

    for(i=0; i<NO_OF_THREADS; i++)
    {
        pthread_create(&printThreads[i], NULL, print_function,&i);
    }

    int j;
    for(j=0;j<NO_OF_THREADS;j++)
        pthread_join(printThreads[j],NULL);
    puts("Main over and out");
    return 0;
}

当我修改代码以打印pthread_self()以及*i时,我得到了输出:

0x10800f000: Hello world from thread 1
0x10800f000: Hello world from thread 4
0x10800f000: Hello world from thread 5
0x10800f000: Hello world from thread 5
0x10800f000: Hello world from thread 5
0x10800f000: Hello world from thread 5
0x10800f000: Hello world from thread 5
0x10800f000: Hello world from thread 5
0x10800f000: Hello world from thread 5
0x10800f000: Hello world from thread 5
0x108092000: Hello world from thread 5
0x108115000: Hello world from thread 5
0x108198000: Hello world from thread 5
0x10821b000: Hello world from thread 5

其中四个线程只看到了值5;其中一个(大概是'线程0')也看到了值1和4。这种行为也是非确定性的。这是另一次运行的开始:

0x10432b000: Hello world from thread 3
0x1043ae000: Hello world from thread 4
0x104431000: Hello world from thread 4
0x1044b4000: Hello world from thread 4
0x104537000: Hello world from thread 5
0x10432b000: Hello world from thread 5
0x1043ae000: Hello world from thread 5

在这两种情况下,其余条目都是回显5的各种线程。