测试“pthread_create”函数行为

时间:2013-06-24 15:36:33

标签: c multithreading pthreads

我是多线程编程的新手,我对“pthread_create”行为有疑问 这是代码:

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

#define NTHREADS      10
#define ARRAYSIZE   1000000
#define ITERATIONS   ARRAYSIZE / NTHREADS

double  sum=0.0, a[ARRAYSIZE];
pthread_mutex_t sum_mutex;


void *do_work(void *tid) 
{
  int i, k=0,start, *mytid, end;
  double mysum=0.0;

  mytid = (int *) tid;
  start = (*mytid * ITERATIONS);
  end = start + ITERATIONS;
  printf ("Thread %d doing iterations %d to %d\n",*mytid,start,end-1);  
  for (i=start; i < end ; i++) {
    a[i] = i * 1.0;
    mysum = mysum + a[i];
    }

  sum = sum + mysum;

}


int main(int argc, char *argv[])
{
  int i, start, tids[NTHREADS];
  pthread_t threads[NTHREADS];
  pthread_attr_t attr;

  for (i=0; i<NTHREADS; i++) {
    tids[i] = i;
    pthread_create(&threads[i], NULL/*&attr*/, do_work, (void *) &tids[i]);
   }

  /* Wait for all threads to complete then print global sum */ 
/*
  for (i=0; i<NTHREADS; i++) {
    pthread_join(threads[i], NULL);
  }*/
  printf ("Done. Sum= %e \n", sum);

  sum=0.0;
  for (i=0;i<ARRAYSIZE;i++){ 
  a[i] = i*1.0;
  sum = sum + a[i]; }
  printf("Check Sum= %e\n",sum);

}

执行结果是:

Thread 1 doing iterations 100000 to 199999
Done. Sum= 0.000000e+00 
Thread 0 doing iterations 0 to 99999
Thread 2 doing iterations 200000 to 299999
Thread 3 doing iterations 300000 to 399999
Thread 8 doing iterations 800000 to 899999
Thread 4 doing iterations 400000 to 499999
Thread 5 doing iterations 500000 to 599999
Thread 9 doing iterations 900000 to 999999
Thread 7 doing iterations 700000 to 799999
Thread 6 doing iterations 600000 to 699999
Check Sum= 8.299952e+11

创建所有线程并且执行不是顺序的(删除pthread_join),但函数do_work按顺序执行并依赖于线程。它意味着迭代0到99999由线程0完成,迭代100000到199999由线程1等完成...

问题在于这里为什么例如迭代0到99999不是由线程2完成的?

3 个答案:

答案 0 :(得分:2)

这是因为迭代范围是根据以下行中从0到N的线程数计算的:

start = (*mytid * ITERATIONS);

您可以在循环中创建并传递该数字:

for (i=0; i<NTHREADS; i++) {
    tids[i] = i;
    ...

换句话说,当N为非负数时,2​​ + N将永远不会为0,从而在0到99999之间执行迭代。

答案 1 :(得分:1)

我认为你对于什么线程感到困惑。 将每个线程视为自己的程序。如果你同时运行10个程序,它们将“同时”运行,即这10个程序的指令将被交错,但在每个程序中,所有指令都以确定的顺序执行。 线程也一样。您可以通过在创建线程时传递线程id参数来定义每个线程将迭代的数字。

答案 2 :(得分:0)

您正在将tids[i] th 变量的地址发送给线程i并根据它进行打印。在这种情况下,N th 主题将始终从N000000打印到N999999,而不会在所有试运行中进行任何更改。

mytid = (int *) tid;
start = (*mytid * ITERATIONS);
end = start + ITERATIONS;

对于线程2,它将表现为,

mytid = (int *) tid;                    // *mytid = 2
start = ( 2 * ITERATIONS);              // 2000000
end = ( 2 * ITERATIONS) + ITERATIONS;   // 2999999

因此将2000000打印到2999999。因此,您不能指望thread 2打印0 to 99999


使用像sum之类的全局变量是明智的,它们在线程之间共享,没有任何类型的锁定机制。他们会带来意想不到的结果在这里使用pthread_mutex可以解决这个问题。