简体   繁体   English

C 中的 pthreads:如何阻止线程相互干扰?

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

I'm new to using pthreads.我是使用 pthreads 的新手。 I want to create a program where six different threads will each output a different number.我想创建一个程序,其中六个不同的线程将每个 output 一个不同的数字。 The threads can run in any order, however, each thread should run only once.线程可以按任何顺序运行,但是,每个线程只能运行一次。

So, a possible output would be:因此,可能的 output 将是:

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

Or it could be in any other order.或者它可以是任何其他顺序。

#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;
}

When I run the program, I have this problem of the threads interfering with each other.当我运行程序时,我遇到了线程相互干扰的问题。 I am not sure if some of the threads are running twice?我不确定某些线程是否运行了两次? However, I think the problem is some of the threads are using the apple_num pointer from a different thread.但是,我认为问题在于某些线程正在使用来自不同线程的apple_num指针。

Here are two sample outputs I got:这是我得到的两个示例输出:

Output 1: Output 1:

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

Output 2: Output 2:

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

I don't fully understand what is causing the problem.我不完全明白是什么导致了这个问题。 I've heard that threads can sometimes share variables?我听说线程有时可以共享变量? I don't know if I should use a mutex lock to somehow get the threads to run one-at-a-time.我不知道我是否应该使用互斥锁以某种方式让线程一次运行一个。

How can I edit my code to solve this?如何编辑我的代码来解决这个问题?

If somebody else has asked a similar question, please direct me to their question.如果其他人问过类似的问题,请引导我回答他们的问题。 I couldn't find anything when I researching.我在研究时找不到任何东西。

Each of your threads gets a pointer to the very same local variable apple_num which is being changed in the loop by the main thread.您的每个线程都有一个指向同一个局部变量apple_num的指针,该变量正在由主线程在循环中更改。 Since threads start asynchronously, the value of local variable apple_num in the main thread is indeterminate from the perspective of any other thread.由于线程是异步启动的,因此主线程中的局部变量apple_num的值在任何其他线程看来都是不确定的。

You need to pass a copy of that variable to each thread.您需要将该变量的副本传递给每个线程。

One fix is to cast int to void* and back:一种解决方法是将int转换为void*并返回:

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

As they mention in the comments, intptr_t and uintptr_t (from <stdint.h> ) may be more appropriate for round-trip without loss, eg uintptr_t -> void* -> uintptr_t .正如他们在评论中提到的那样, intptr_tuintptr_t (来自<stdint.h> )可能更适合无损失的往返,例如uintptr_t -> void* -> uintptr_t But C standard doesn't require any integers to round-trip to void* and back, it only requires void* -> intptr_t and back.但是 C 标准不需要任何整数来往返void*并返回,它只需要void* -> intptr_t并返回。

In a more realistic scenario, you may like to pass more than just one integer to a thread, namely, a struct .在更现实的场景中,您可能希望将多个 integer 传递给线程,即struct And that's the rationale for the thread start function to receive a single void* argument - it can point to an object of any data type (POSIX requires void* to also be able to store function pointers).这就是线程启动 function 以接收单个void*参数的基本原理 - 它可以指向任何数据类型的 object(POSIX 需要void*也能够存储 ZC1C425268E18385D14ZF5074 指针)。

An example of passing a structure to a thread (without relying on implementation-defined conversion of integers to void* and back):将结构传递给线程的示例(不依赖于实现定义的整数到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;
}

Note, that you don't have to allocate the thread arguments structure on the heap ( malloc ).请注意,您不必在堆 ( malloc ) 上分配线程 arguments 结构。 If you pass an automatic variable (on the stack) to a thread, you must make sure that the variable is unchanged and still exists when the thread accesses it.如果您将自动变量(在堆栈上)传递给线程,则必须确保该变量未更改并且在线程访问它时仍然存在。 Allocating the thread arguments structure from the heap is the safest and solves this problem at the expense of malloc / free calls.从堆中分配线程 arguments 结构是最安全的,并且以malloc / free调用为代价解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM