如何使用 for 循环创建多个 pthread?

How to create multiple pthreads with a for loop?

这应该是一项简单的任务,但我无法让它工作。下面的代码应该是不言自明的,我正在尝试创建 4 个线程,每个线程打印一个与我在 printMessage 中定义的数组不同的字符串。

#include <pthread.h>
#include <iostream>

using namespace std;


void *printMessage(void *arg)
{
   int argInt = *((int*) arg);

   const char* my_messages[4] = {"English: Hello!", 
    "French: Bonjour!", "Spanish: Hola!", 
    "German: Guten Tag!" };

   cout << my_messages[argInt] << "\n";
   pthread_exit(0);
}


int main()
{
   pthread_t id[4];

   int rc;

   // Create thread(s)
   for(int i = 0; i < 4; i++) {
      int index = i;
      rc = pthread_create(&id[index], NULL, printMessage, (void*) &index);
      
      if (rc) {
          cout << "ERROR; return code from pthread_create() is " << rc << endl;
          return -1;
      }
   }


   pthread_exit(0);
}

执行此操作时,数组中的最后一个字符串“German: Guten Tag!”打印了 4 次。我注意到的另一个奇怪的情况是,如果我放弃看似多余的 'index' 变量并使用 'i' 代替,则不会打印任何内容。作为 c++ 和多线程的新手,这让我很困惑,我们将不胜感激。谢谢!

  rc = pthread_create(&id[index], NULL, printMessage, (void*) &index);

这将创建一个新的执行线程,并将指向名为 index.

的局部变量的指针作为参数传递给它

您绝对不能保证新的执行线程实际上在 pthread_create returns 之前开始执行,或者 之后立即开始执行 。通常在新的执行线程开始运行之前会有一小段延迟。您可以保证的是,新的执行线程将 运行、真正启动

与此同时,pthread_create() returns 到达循环的末尾,传递指针的 index 变量被销毁并消失在黑洞中再也见不到了。一段时间后,新的执行线程开始搅动,获取其线程参数,该参数现在指向一个已销毁的对象。未定义的行为。

您有多种选择。

  1. 使用new在动态范围内分配线程参数(并在完成后让执行线程delete成为newed对象)。

  2. 使用额外的多线程资源,比如mutex和condition variables,来协调创建新执行线程的歌舞,让父执行线程一直等到新的执行线程读取其参数,并将其放在手边。

您将 int index 定义为循环体内的局部变量,因此它将在 pthread_create() 退出后超出范围,因此 printMessage() 显示 未定义的行为 通过访问无效内存(内存可能在每次循环迭代中被重用)。

您需要:

  • index 值移动到循环之前声明的数组中,并保留在范围内,直到所有线程都终止。就像你在处理 id[] 数组一样。
#include <pthread.h>
#include <iostream>
using namespace std;

void* printMessage(void *arg)
{
   int argInt = *static_cast<int*>(arg);

   const char* my_messages[4] = {"English: Hello!", 
    "French: Bonjour!", "Spanish: Hola!", 
    "German: Guten Tag!" };

   cout << my_messages[argInt] << "\n";

   return NULL;
}

int main()
{
   pthread_t id[4];
   int index[4];
   int rc, num = 0;

   // Create thread(s)
   for(int i = 0; i < 4; i++) {
      index[i] = i;
      rc = pthread_create(&id[i], NULL, printMessage, &index[i]);
      if (rc) {
          cout << "ERROR; return code from pthread_create() is " << rc << endl;
          break;
      }
      ++num;
   }

   // wait for threads to terminate ...
   for(int i = 0; i < num; i++) {
       pthread_join(id[i], NULL);
   }

   return 0;
}
  • index 传递给每个线程,而不是将 指针 传递给 index
#include <pthread.h>
#include <iostream>
using namespace std;

void* printMessage(void *arg)
{
   int argInt = reinterpret_cast<int>(arg);

   const char* my_messages[4] = {"English: Hello!", 
    "French: Bonjour!", "Spanish: Hola!", 
    "German: Guten Tag!" };

   cout << my_messages[argInt] << "\n";

   return NULL;
}

int main()
{
   pthread_t id[4];
   int rc, num = 0;

   // Create thread(s)
   for(int i = 0; i < 4; i++) {
      rc = pthread_create(&id[i], NULL, printMessage, reinterpret_cast<void*>(i));
      if (rc) {
          cout << "ERROR; return code from pthread_create() is " << rc << endl;
          break;
      }
      ++num;
   }

   // wait for threads to terminate ...
   for(int i = 0; i < num; i++) {
       pthread_join(id[i], NULL);
   }

   return 0;
}
  • 动态分配index,让线程销毁传入的int
#include <pthread.h>
#include <iostream>
using namespace std;

void* printMessage(void *arg)
{
   int *argInt = static_cast<int*>(arg);

   const char* my_messages[4] = {"English: Hello!", 
    "French: Bonjour!", "Spanish: Hola!", 
    "German: Guten Tag!" };

   cout << my_messages[*argInt] << "\n";
   delete argInt;

   return NULL;
}

int main()
{
   pthread_t id[4];
   int rc, num = 0;

   // Create thread(s)
   for(int i = 0; i < 4; i++) {
      int *index = new int(i);
      rc = pthread_create(&id[i], NULL, printMessage, index);
      if (rc) {
          cout << "ERROR; return code from pthread_create() is " << rc << endl;
          delete index;
          break;
      }
      ++num;
   }

   // wait for threads to terminate ...
   for(int i = 0; i < num; i++) {
       pthread_join(id[i], NULL);
   }

   return 0;
}

话虽这么说,您确实应该直接使用 std::thread 而不是 pthreads(如果需要,让 std::thread 实现在内部使用 pthreads):

#include <iostream>
#include <thread>
using namespace std;

void printMessage(int arg)
{
   const char* my_messages[4] = {"English: Hello!", 
    "French: Bonjour!", "Spanish: Hola!", 
    "German: Guten Tag!" };

   cout << my_messages[arg] << "\n";
}

int main()
{
   thread thrd[4];

   // Create thread(s)
   for(int i = 0; i < 4; i++) {
      thrd[i] = thread(printMessage, i);
   }

   // wait for threads to terminate ...
   for(int i = 0; i < 4; i++) {
       thrd[i].join();
   }

   return 0;
}