【问题标题】:pthreads shared memory between threadspthreads 线程间共享内存
【发布时间】:2014-04-19 16:09:43
【问题描述】:

所以我有一小段代码,理论上可以很容易地进行parrelized。

结构很简单,和下面的很相似:

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 的值也改变了?

【问题讨论】:

  • 你打算如何将它传递给线程?
  • 这取决于你如何传递变量,以及它在哪里声明。每个线程都有自己的堆栈,因此它们有自己的局部变量(除非它们是静态的) C 中的所有内容都是按值传递的,因此会制作一个副本,但您可能会做其他事情,例如将指针传递给i。但不清楚你所说的线程函数是什么意思,函数不是线程的——你创建线程,线程调用函数。
  • 我相信他调用'线程函数'就是你调用pthread_create时提供的函数

标签: c linux multithreading pthreads


【解决方案1】:

如果您提供指向多个线程的指针,它们的行为可能会以不确定的方式修改指向的值。如果您在线程之间共享变量,您应该使用信号量或互斥锁来管理线程之间的读/写访问。

如果您知道线程只访问不同的内存位置,则无需这样做。例如,如果每个线程写入同一个数组但索引不同,则不需要保护数组。

编辑:

如果您提供变量i 的地址,那么是的,它将通过循环在线程外部进行修改。但是,如果您在循环中创建一个临时变量并传递其地址,那么您会没事的。此示例可能会帮助您了解正在发生的事情: http://timmurphy.org/2010/05/04/pthreads-in-c-a-minimal-working-example/

在 C 语言中,只要您提供指向函数的指针,它所指向的值就可以从该函数的内部和外部进行修改(无论它是否在同一个线程上)。 pthread_create 要求您以 void * 的形式提供启动例程的参数,因此任何具有指向同一变量的指针的东西都可以随时修改其值。

正如@Shahbaz 所建议的,您可能对 OpenMP 感兴趣。使用 OpenMP,您可以在代码中添加 pragma,以便于创建线程。您还可以指定线程是否共享一个变量。

【讨论】:

  • 每个线程都按照您所说的方式写入相同的数组但不同的索引。索引由 for 循环中的“i”变量定义。现在我想知道的是,如果我调用该函数并将 i 作为变量传递给它,然后 for 循环继续并且 i 递增。我在运行的线程中是否也会增加?或者更基本的说法是:我传递给函数的 i 是否与当前 for 循环中的 i 变量在内存中的 i 相同?
  • 这取决于你如何将它传递给函数。如果您将地址提供给i 是的,它将因为循环而在外部被修改,如果您在循环中创建一个临时变量并传递其地址,那么您会没事的。此示例可能会帮助您了解正在发生的事情:timmurphy.org/2010/05/04/…
【解决方案2】:

如果您将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]);

在函数中:

void *func(void *arg)
{
    struct thread_data *data = arg;

    for (int i = data->start; i < data->end; ++i)
        /* do some work */
}

您可能也有兴趣了解 OpenMP,它旨在完全自动化您的要求。

【讨论】:

    猜你喜欢
    • 2016-03-01
    • 1970-01-01
    • 2012-07-06
    • 2020-11-10
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    相关资源
    最近更新 更多