所以我有一小段代码,理论上可以很容易地进行组合。
结构非常简单,与以下内容非常相似:
for (int i = 0; i < some_value; ++i) {
// we have a function called do_stuff
// somewhere in the code
// Create a new pthread
// using do_stuff as start routine
}
现在所有变量都不在线程之间共享。也就是说,线程之间不需要相互之间的通信。但是我确实使用变量i
将数据写入数组等。
我想知道的是:如果我将变量i
作为pthread启动例程的参数传递,并且i
的值发生了变化(因为i
在下一个时会增加循环迭代),现有线程中i
的值是否也会改变?
答案 0 :(得分:5)
如果您将i
的地址传递给所有函数,并且每个函数都尝试修改它,那么当然i
搞乱了,因为它们都具有相同变量的地址。你需要的是给每个线程提供他们需要处理的范围,让他们用局部变量迭代它。像这样:
struct thread_data
{
int start;
int end;
pthread_t tid;
};
struct thread_data td[N]; // assuming N threads
/* divide up the ranges */
for (i = 0; i < N; ++i)
td[i] = (struct thread_data){ .start = i*len/N, .end = (i+1)*len/N };
td[N-1].end = len;
/* create the threads */
for (i = 0; i < N; ++i)
pthread_create(&td[i].tid, NULL, func, &td[i]);
和func:
void *func(void *arg)
{
struct thread_data *data = arg;
for (int i = data->start; i < data->end; ++i)
/* do some work */
}
您可能也有兴趣了解OpenMP,它旨在自动完全满足您的要求。
答案 1 :(得分:1)
如果您提供指向多个线程的指针,则它们的行为可能会修改以不确定方式指向的值。如果在线程之间共享变量,则应使用信号量或互斥量来管理线程之间的读/写访问。
如果您知道线程只访问不同的内存位置,则不需要这样做。例如,如果每个线程在同一个数组中写入但是对于不同的索引,则不需要保护数组。
修改强>
如果提供变量i
的地址,那么它将在循环外部修改。但是,如果在循环中创建一个临时变量并传递其地址,那么你会没事的。这个例子可以帮助您了解发生了什么:
http://timmurphy.org/2010/05/04/pthreads-in-c-a-minimal-working-example/
在C中,无论何时提供指向函数的指针,它指向的值都可以从该函数的内部和外部修改(无论它是否在同一个线程上)。 pthread_create
要求您以void *
的形式提供起始例程的参数,因此任何具有指向同一变量的指针的内容都可以随时修改其值。
正如@Shahbaz建议的那样,您可能对OpenMP感兴趣。使用OpenMP,您可以在代码中添加编译指示以便于创建线程。您还可以指定线程是否共享变量。