将整数(不是来自堆)作为参数发送给线程的行为
Behavior on sending an integer (not from heap) as an argument to the thread
我想从同一个函数创建具有不同索引值的线程。我总是将变量从堆发送到线程。但是我不想从堆中发送,因为我想在这里发送一个不同的变量来知道所有这些变量的索引;在这种情况下,如果我从堆中发送,索引值可能会在其他人中更改而尚未存储。
#include <pthread.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
struct Myarg{
int index;
};
void *foo(void *arg)
{
struct Myarg *a = (struct Myarg* ) arg;
printf("\nfoo%d executed", a->index);
pthread_exit(NULL);
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t tid[6];
struct Myarg arg;
for (int i = 0; i < 6; i++)
{
arg.index = i;
if (pthread_create(&tid[i], NULL, foo, &arg) != 0)
{
printf("\nerror!");
exit(-1);
}
}
for (int i = 0; i < 6; i++)
{
if (pthread_join(tid[i], NULL) != 0)
{
printf("\nerror!");
exit(-1);
}
}
return 0;
}
这是这段代码的几个输出:
foo1 executed
foo2 executed
foo3 executed
foo4 executed
foo5 executed
foo5 executed
foo1 executed
foo4 executed
foo3 executed
foo5 executed
foo5 executed
foo2 executed
我分享这段代码只是为了表达我的意图。这是我预期的各种结果的示例:
foo1 executed
foo4 executed
foo3 executed
foo5 executed
foo6 executed
foo2 executed
我想我可以通过从堆中取出整数并创建六个不同的参数变量来实现这个意图。但我想知道这里究竟发生了什么?还是可以在不创建 6 个不同变量的情况下实现这个目标?
您正在将 same 结构的地址发送到线程的 each。这意味着当每个线程读取它时,关于结构恰好包含什么值的竞争条件。
最简单的解决方案是拥有一个结构数组并将不同的数组元素传递给每个结构。
struct Myarg arg[6];
for (int i = 0; i < 6; i++)
{
arg[i].index = i;
if (pthread_create(&tid[i], NULL, foo, &arg[i]) != 0)
{
printf("\nerror!");
exit(-1);
}
}
此外,您没有在代码中的任何地方使用堆,因为您从不调用任何 malloc
函数族。所有相关变量都是局部变量(在大多数实现中)存在于堆栈中。
或者,您可以为堆上的每个线程分配一个结构并将其传入:
for (int i = 0; i < 6; i++)
{
struct Myarg *arg = malloc(sizeof(*arg));
arg->index = i;
if (pthread_create(&tid[i], NULL, foo, arg) != 0)
{
printf("\nerror!");
exit(-1);
}
}
并且线程将负责释放内存:
struct Myarg *a = arg;
printf("\nfoo%d executed", a->index);
free(a);
pthread_exit(NULL);
我想从同一个函数创建具有不同索引值的线程。我总是将变量从堆发送到线程。但是我不想从堆中发送,因为我想在这里发送一个不同的变量来知道所有这些变量的索引;在这种情况下,如果我从堆中发送,索引值可能会在其他人中更改而尚未存储。
#include <pthread.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
struct Myarg{
int index;
};
void *foo(void *arg)
{
struct Myarg *a = (struct Myarg* ) arg;
printf("\nfoo%d executed", a->index);
pthread_exit(NULL);
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t tid[6];
struct Myarg arg;
for (int i = 0; i < 6; i++)
{
arg.index = i;
if (pthread_create(&tid[i], NULL, foo, &arg) != 0)
{
printf("\nerror!");
exit(-1);
}
}
for (int i = 0; i < 6; i++)
{
if (pthread_join(tid[i], NULL) != 0)
{
printf("\nerror!");
exit(-1);
}
}
return 0;
}
这是这段代码的几个输出:
foo1 executed
foo2 executed
foo3 executed
foo4 executed
foo5 executed
foo5 executed
foo1 executed
foo4 executed
foo3 executed
foo5 executed
foo5 executed
foo2 executed
我分享这段代码只是为了表达我的意图。这是我预期的各种结果的示例:
foo1 executed
foo4 executed
foo3 executed
foo5 executed
foo6 executed
foo2 executed
我想我可以通过从堆中取出整数并创建六个不同的参数变量来实现这个意图。但我想知道这里究竟发生了什么?还是可以在不创建 6 个不同变量的情况下实现这个目标?
您正在将 same 结构的地址发送到线程的 each。这意味着当每个线程读取它时,关于结构恰好包含什么值的竞争条件。
最简单的解决方案是拥有一个结构数组并将不同的数组元素传递给每个结构。
struct Myarg arg[6];
for (int i = 0; i < 6; i++)
{
arg[i].index = i;
if (pthread_create(&tid[i], NULL, foo, &arg[i]) != 0)
{
printf("\nerror!");
exit(-1);
}
}
此外,您没有在代码中的任何地方使用堆,因为您从不调用任何 malloc
函数族。所有相关变量都是局部变量(在大多数实现中)存在于堆栈中。
或者,您可以为堆上的每个线程分配一个结构并将其传入:
for (int i = 0; i < 6; i++)
{
struct Myarg *arg = malloc(sizeof(*arg));
arg->index = i;
if (pthread_create(&tid[i], NULL, foo, arg) != 0)
{
printf("\nerror!");
exit(-1);
}
}
并且线程将负责释放内存:
struct Myarg *a = arg;
printf("\nfoo%d executed", a->index);
free(a);
pthread_exit(NULL);