使用for循环创建多个线程时的奇怪行为

时间:2016-10-29 00:57:18

标签: c linux multithreading pthreads

我正在制作一个多线程程序,模拟一个电梯和49个人,每个人都有自己的线程,以及电梯。我处于开始阶段,只是尝试创建线程并验证它们是否正常工作。

我有一个名为person_threads的pthreads数组,我试图在for循环中初始化,在循环中我发送带有线程号的消息并在线程中打印出来。由于某种原因,我得到了奇怪的行为,几乎就像for循环在创建一些线程之前没有正确迭代(参见循环和输出)。这种行为是随机的,每次运行都是不同的,我不确定我需要做什么才能让线程正确创建。如果您对可能导致此问题的原因有任何见解,请提供帮助。

代码

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

#define MAX_PERSONS 49

void *person(void *myvar);
void *elevator(void *myvar);

int main(int argc, char *argv[]){

    pthread_t elevator_thread;
    pthread_t person_threads[MAX_PERSONS]; //My array of threads

    char *elev_msg = "Elevator thread started";

    pthread_create(&elevator_thread, NULL, elevator, (void *) elev_msg);

    //Here is where I try to initialize messages and threads,
    //see Persons function and output    

    for (int i = 0; i < MAX_PERSONS; i++){
        char msg[50];
        snprintf(msg, sizeof msg, "Person thread %d started", i);
        pthread_create(&person_threads[i], NULL, person, (void *) msg);
    }

    printf("Main function after pthread_creates\n");

    pthread_join(elevator_thread, NULL);
    for (int i = 0; i < MAX_PERSONS; i++){
        pthread_join(person_threads[i], NULL);
    }

    return 0;
}

void *person(void *myvar){
    char *msg;
    msg = (char *) myvar;

    printf("%s\n", msg);

    return NULL;
}

void *elevator(void *myvar){
    char *msg;
    msg = (char *) myvar;

    printf("%s\n", msg);

    return NULL;
}

输出

brendan@brendan-Ubuntu-Desk:~/Documents/OS-Project2$ ./elevator 
Elevator thread started
Person thread 7 started
Person thread 7 started
Person thread 7 started
Person thread 7 started
Person thread 7 started
Person thread 7 started
Person thread 7 started
Person thread 8 started
Person thread 9 started
Person thread 10 started
Person thread 12 started
Person thread 12 started
Person thread 14 started
Person thread 15 started
Person thread 15 started
Person thread 16 started
Person thread 17 started
Person thread 18 started
Person thread 19 started
Person thread 20 started
Person thread 21 started
Person thread 22 started
Person thread 23 started
Person thread 24 started
Person thread 25 started
Person thread 26 started
Person thread 27 started
Person thread 28 started
Person thread 29 started
Person thread 30 started
Person thread 31 started
Person thread 32 started
Person thread 33 started
Person thread 34 started
Person thread 35 started
Person thread 36 started
Person thread 37 started
Person thread 38 started
Person thread 39 started
Person thread 40 started
Person thread 41 started
Person thread 42 started
Person thread 43 started
Person thread 44 started
Person thread 45 started
Person thread 46 started
Person thread 47 started
Person thread 48 started
Main function after pthread_creates
Person thread 48 started

注意有多个7s,15s,12s和48s。每次运行时此行为都是随机的。我注意到它实际上总是创建50个线程但我需要正确初始化数组。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

原因如下:

for (int i = 0; i < MAX_PERSONS; i++){
    char msg[50];
    snprintf(msg, sizeof msg, "Person thread %d started", i);
    pthread_create(&person_threads[i], NULL, person, (void *) msg);
}

msg参数仅在块范围内的主线程中有效。您需要在堆上分配msg缓冲区并将其释放到子线程中。

答案 1 :(得分:1)

你的错误在这里:

  for (int i = 0; i < MAX_PERSONS; i++){
    char msg[50];

由于您正在为消息缓冲区使用局部变量,因此在循环的每次迭代中,缓冲区都会在堆栈上创建然后被销毁。然后在下一次迭代中,您可能会重复使用相同的内存并覆盖它。

您需要为每个线程使用msg动态分配malloc,这样它们都有自己的消息缓冲区,而不会被共享并被覆盖。

答案 2 :(得分:0)

正如其他人提到的那样,msg的内存会在循环开始(或结束)的那一刻被释放。

除了在堆上分配之外,你可以像这样定义一个“字符串”数组:

int main(int argc, char *argv[]){

  pthread_t elevator_thread;
  pthread_t person_threads[MAX_PERSONS]; //My array of threads
  char msg[MAX_MSG_LEN + 1][MAX_PERSONS];
  char *elev_msg = "Elevator thread started";

  pthread_create(&elevator_thread, NULL, elevator, (void *) elev_msg);

  for (size_t i = 0; i < MAX_PERSONS; i++){
    snprintf(msg[i], sizeof msg, "Person thread %zu started", i);
    pthread_create(&person_threads[i], NULL, person, msg[i]);
  }

  ...

甚至更好地汇集了属于一起的东西:

struct Person_Thread 
{
  pthread_t thread;
  char msg[MAX_MSG_LEN + 1];
};

int main(int argc, char *argv[]){

  pthread_t elevator_thread;
  struct Person_Thread person_threads[MAX_PERSONS]; //My array of threads
  char *elev_msg = "Elevator thread started";

  pthread_create(&elevator_thread, NULL, elevator, (void *) elev_msg);

  for (size_t i = 0; i < MAX_PERSONS; i++){
    snprintf(person_threads[i].msg, sizeof person_threads[i].msg, 
      "Person thread %zu started", i);

    pthread_create(&person_threads[i].thread, NULL, person, 
      person_threads[i].msg]);
  }

  ...
相关问题