如何解决如何使用 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
变量被销毁,它消失在一个再也看不见的黑洞中。一段时间后,新的执行线程开始搅动,获取其线程参数,该参数现在指向一个已销毁的对象。未定义的行为。
您有多种选择。
-
使用
new
在动态范围内分配线程参数(并让执行线程delete
完成后new
对象)。 -
使用额外的多线程资源,例如互斥量和条件变量,来协调创建新执行线程所涉及的歌舞,以便父执行线程等待,直到新执行线程读取其参数,并随手可得。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。