微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

这应该是一个简单的任务,但我无法让它工作。下面的代码应该是不言自明的,我正在尝试创建 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);
}

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

解决方法

您将 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!","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],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!","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],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!","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;
}
,
  rc = pthread_create(&id[index],(void*) &index);

这会创建一个新的执行线程,并将一个指向名为 index 的局部变量的指针作为参数传递给它。

无论如何,您绝对不能保证新的执行线程在 pthread_create 返回之前实际开始执行,或者在此之后立即。通常在新的执行线程启动之前会有一个小的延迟。唯一可以保证的是新的执行线程将开始运行,马上就可以了

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

您有多种选择。

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

  2. 使用额外的多线程资源,例如互斥量和条件变量,来协调创建新执行线程所涉及的歌舞,以便父执行线程等待,直到新执行线程读取其参数,并随手可得。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。