簡體   English   中英

pthread_join 后局部變量值不正確

[英]Incorrect local variable value after pthread_join

我試圖通過將數組拆分為大小為 10 的段來使用 pthread 庫總結 1000 個元素的整數數組(其中每個元素為 1)。因此,有效地使用了 100 個線程來執行此操作。 此並行操作的結果符合預期 (1000)。 但有趣的是,在我第一次調用pthread_join()之后,我在創建線程之前計算的順序總和被設置為零。 不確定我是否在這里遺漏了什么。 有人可以在這里發現錯誤嗎?

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

#define SEGMENT_SIZE 10
#define NUM_THREADS 100
int *array = NULL;

void* segment_sum(void *args)
{
        int index = (int)args;
        int sum = 0;

        for (int i = index * SEGMENT_SIZE; i < (index + 1) * SEGMENT_SIZE; i++) {
                sum += array[i];
        }

        return (void *)sum;
}

int main()
{
        pthread_t thread[NUM_THREADS];
        int res = 0;
        int seq_res = 0;
        int par_res = 0;

        array = calloc(1, sizeof(int) * NUM_THREADS * SEGMENT_SIZE);
        for (int i = 0; i < NUM_THREADS * SEGMENT_SIZE; i++) {
                array[i] = 1;
                seq_res += 1;
        }


        for (int i = 0; i < NUM_THREADS; i++) {
                res = pthread_create(&thread[i], NULL, segment_sum, (void *)i);
                if (res != 0) {
                        printf("\nError creating new thread");
                }
        }

        printf("\nindex = %d", seq_res);                // the sequential sum here is 1000

        for (int i = 0; i < NUM_THREADS; i++) {
                int sum = 0;
                res = pthread_join(thread[i], (void **)&sum);
                if (res != 0) {
                        printf("\nError creating new thread");
                }
                printf("\nindex = %d", seq_res);        // Here it is becoming zero!!!

                par_res += sum;
        }

        printf("\nmultithreaded sum: %d single threaded sum: %d\n", par_res, seq_res);
}

當你編譯你的程序時,盡量消除警告,因為它們經常指出不可移植的行為或隱藏的錯誤。 這里匯編指出以下幾點:

pte.c: In function 'segment_sum':
pte.c:11:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   11 |         int index = (int)args;
      |                     ^
pte.c:18:16: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   18 |         return (void *)sum;
      |                ^
pte.c: In function 'main':
pte.c:36:69: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   36 |                 res = pthread_create(&thread[i], NULL, segment_sum, (void *)i);
      |                                                                     ^

傳遞給線程的參數是將指針轉換為“int”。 建議傳遞一個“int”的地址。 因此,您可以定義每線程上下文:

struct thd_ctx {
  pthread_t thread;
  int index;
  int sum;
};

pthread_join() 被傳遞一個指針的地址,該指針將獲得線程存儲其結果的內存位置的地址。 線程必須返回此內存位置的地址,而不是存儲在其中的值。 此外,線程不應返回未指定的自動變量(即在其堆棧中)的地址。 結果必須是直接或通過pthread_exit()返回的全局變量(或從連接線程可見的“某些東西” )的地址 在程序的這個增強中,我們使用線程上下文中“sum”字段的地址:

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

#define SEGMENT_SIZE 10
#define NUM_THREADS 100
int *array = NULL;


struct thd_ctx {
  pthread_t thread;
  int index;
  int sum;
};


void *segment_sum(void *args)
{
  int i;
  struct thd_ctx *ctx = (struct thd_ctx *)args;

  ctx->sum = 0;

  for (i = ctx->index * SEGMENT_SIZE; i < (ctx->index + 1) * SEGMENT_SIZE; i++) {
    ctx->sum += array[i];
  }

  return (void *)&(ctx->sum);
}


int main(void)
{
  struct thd_ctx thd_ctx[NUM_THREADS];
  int res = 0;
  int seq_res = 0;
  int par_res = 0;
  int i;

  array = calloc(1, sizeof(int) * NUM_THREADS * SEGMENT_SIZE);
  if (!array) {
    fprintf(stderr, "calloc(): error %d\n", errno);
    return 1;
  }

  for (i = 0; i < NUM_THREADS * SEGMENT_SIZE; i++) {
    array[i] = 1;
    seq_res += 1;
  }

  for (i = 0; i < NUM_THREADS; i++) {
    thd_ctx[i].index = i;
    res = pthread_create(&(thd_ctx[i].thread), NULL, segment_sum, (void *)&(thd_ctx[i]));
    if (res != 0) {
      fprintf(stderr, "Error %d creating new thread#%d\n", res, i);
      free(array);
      return 1;
    }
  }

  printf("Index = %d\n", seq_res);   // the sequential sum here is 1000

  for (i = 0; i < NUM_THREADS; i++) {
    int *sum = 0;
    res = pthread_join(thd_ctx[i].thread, (void **)&(sum));
    if (res != 0) {
      printf("Error %d joining thread#%d", res, i);
      free(array);
      return 1;
    }

    par_res += *sum;

    printf("sum = %d\n", par_res);
  }

  printf("\nMultithreaded sum: %d single threaded sum: %d\n", par_res, seq_res);

  free(array);

  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM