簡體   English   中英

C 中的 pthreads:如何阻止線程相互干擾?

[英]pthreads in C: How can I stop the threads from interfering with each other?

我是使用 pthreads 的新手。 我想創建一個程序,其中六個不同的線程將每個 output 一個不同的數字。 線程可以按任何順序運行,但是,每個線程只能運行一次。

因此,可能的 output 將是:

Thread: 5
Thread: 2
Thread: 3
Thread: 6
Thread: 1
Thread: 4

或者它可以是任何其他順序。

#include<stdio.h>
#include<pthread.h>
    
void *apples(void *void_apple_num){
      int *thread_num = (int *) void_apple_num;
      printf("Thread: %d\n", *thread_num);
      return NULL;
}



int main(){
  pthread_t threads[6];
  int apple_num;
  

  for(apple_num=0; apple_num<6; apple_num++){
       pthread_create(&threads[apple_num], NULL, apples, &apple_num);
  }

  for(apple_num=0; apple_num<6; apple_num++){
       pthread_join(threads[apple_num], NULL);
  }    

  return 0;
}

當我運行程序時,我遇到了線程相互干擾的問題。 我不確定某些線程是否運行了兩次? 但是,我認為問題在於某些線程正在使用來自不同線程的apple_num指針。

這是我得到的兩個示例輸出:

Output 1:

Thread: 5
Thread: 0
Thread: 1
Thread: 1
Thread: 2
Thread: 2

Output 2:

Thread: 1
Thread: 4
Thread: 4
Thread: 5
Thread: 1
Thread: 1

我不完全明白是什么導致了這個問題。 我聽說線程有時可以共享變量? 我不知道我是否應該使用互斥鎖以某種方式讓線程一次運行一個。

如何編輯我的代碼來解決這個問題?

如果其他人問過類似的問題,請引導我回答他們的問題。 我在研究時找不到任何東西。

您的每個線程都有一個指向同一個局部變量apple_num的指針,該變量正在由主線程在循環中更改。 由於線程是異步啟動的,因此主線程中的局部變量apple_num的值在任何其他線程看來都是不確定的。

您需要將該變量的副本傳遞給每個線程。

一種解決方法是將int轉換為void*並返回:

void *apples(void* apple_num){
    int thread_num = (int)void_apple_num;
...
    pthread_create(&threads[apple_num], NULL, apples, (void*)apple_num);

正如他們在評論中提到的那樣, intptr_tuintptr_t (來自<stdint.h> )可能更適合無損失的往返,例如uintptr_t -> void* -> uintptr_t 但是 C 標准不需要任何整數來往返void*並返回,它只需要void* -> intptr_t並返回。

在更現實的場景中,您可能希望將多個 integer 傳遞給線程,即struct 這就是線程啟動 function 以接收單個void*參數的基本原理 - 它可以指向任何數據類型的 object(POSIX 需要void*也能夠存儲 ZC1C425268E18385D14ZF5074 指針)。

將結構傳遞給線程的示例(不依賴於實現定義的整數到void*和返回的轉換):

struct ThreadArgs {
    int thread_num;
    // More data members, as needed.
};

void* apples(void* arg){
    struct ThreadArgs* a = arg;
    printf("Thread: %d\n", a->thread_num);
    free(arg);
    return NULL;
}

int main() {
    pthread_t threads[6];
    struct ThreadArgs* a;
    int apple_num;

    for(apple_num=0; apple_num<6; apple_num++){
        a = malloc(sizeof *a);
        a->thread_num = apple_num;
        pthread_create(&threads[apple_num], NULL, apples, a);
    }
    
    for(apple_num=0; apple_num<6; apple_num++)
        pthread_join(threads[apple_num], NULL);
    
    return 0;
}

請注意,您不必在堆 ( malloc ) 上分配線程 arguments 結構。 如果您將自動變量(在堆棧上)傳遞給線程,則必須確保該變量未更改並且在線程訪問它時仍然存在。 從堆中分配線程 arguments 結構是最安全的,並且以malloc / free調用為代價解決了這個問題。

暫無
暫無

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

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