多线程,每个线程都有唯一的变量

时间:2017-04-05 10:45:26

标签: c arrays multithreading scope

我正在尝试为需要类似以下内容的问题实施多线程解决方案

  • 我创建'n'个帖子
  • 我有一个'n - 1'大小的数组
  • 每个线程只应访问其数组的相应元素(即线程0应仅影响数组的元素0,线程1应仅影响元素1,依此类推。)
  • 每个线程将执行与索引'k'
  • 引用数组相同的函数

如何在每次创建线程时更改“k”以使其从0开始,并以“n - 1”结束,以便每个线程只访问其指定的数组元素?

4 个答案:

答案 0 :(得分:1)

这适用于(在POSIX平台上...)并且是他的答案中提到的@Some Programmer Dude方法的实现。它应该是可移植且符合标准的,只要实现提供intptr_t作为类型(它是可选的):

void *start_func( void *arg )
{
    int myID = ( intptr_t ) arg;
       .
       .
       .
    return( NULL );
}

int main( int argc, char **argv )
{
       .
       .
       .
    pthread_t tid[ n ];
    for ( int k = 0; k < n; i++ )
    {
        pthread_create( &tid[ k ], NULL, start_func, ( void * )( intptr_t ) k );
    }
       .
       .
       .
    return( 0 );
}

您需要注意sizeof( int )大于sizeof( intptr_t ) 的任何架构,您的循环值会溢出intptr_t,但是据我所知,这样的架构根本不存在。

答案 1 :(得分:1)

让我强调一下,Andrew Henle接受的答案非常好,并且可以在我曾经使用的每个C环境中工作,即使他在技术上不正确地说它是便携式和符合标准的。

我想我更喜欢以下两种解决方案中的任何一种

  1. 将直接指针传递给元素

    typedef /* whatever */ } MyType;
    MyType* array;
    int main(int argc, char*argv[])
    {
        // find out what n is
        array = calloc(n, sizeof *array);
        // some stuff including filling in array
        pthread_t tid[n];
        for (int k = 0; k < n; k++)
        {
            pthread_create( &tid[k], NULL, startFunc, &array[k]);
        }
        // do stuff including wait for the threads to finish
    }
    
    void startFunc(void* param)
    {
        MyType* myObject = (MyType*)param;
        // Do stuff directly on myObject
        // or if you *really* need to recover k:
        ptrdiff_t k = myObject - array;
    }
    

    我喜欢这个解决方案,因为线程不需要知道它正在处理的单个数据的上下文。

  2. 创建一个上下文类型以传递给线程启动函数并将所需内容放入其中。

    typedef /* whatever */ } MyType;
    MyType* array;
    struct ThreadContext
    {
        pthread_t tid;
        int k;
        MyType *array;
        size_t arraySize;
    }
    
    int main(int argc, char*argv[])
    {
        // find out what n is
        array = calloc(n, sizeof *array);
        // some stuff including filling in the array
        struct Context* contexts = calloc(n, sizeof *contexts);
        for (int k = 0; k < n; k++)
        {
            contexts[k].array = array;
            contexts[k].arraySize = n;
            contexts[k].k = k;
            pthread_create( &(contexts[k].tid), NULL, startFunc, &contexts[k]);
        }
        // do stuff including wait for the threads to finish
    }
    
    void startFunc(void* param)
    {
        struct Context* context= (struct Context*)param;
        doSomethingWithArrayObject(context->array, context->k);
    }
    

    这更像是将回传上下文数据传递给回调函数的常规方式。您可以将所需的所有内容放在Context结构中的线程中,而不是依赖于全局变量。

答案 2 :(得分:0)

虽然有点气馁,但可以k传递给线程函数,并进行一些来回转换。

或者您可以动态分配unsigned int(每个线程一个)来存储k的值,并将该指针传递给线程函数(复制它然后释放分配的内存)。这是安全和便携的。

答案 3 :(得分:0)

正确的方法是:

  • 在创建线程的调用者中分配变量。
  • 在创建时将指向变量的指针作为参数传递给线程。
  • 在线程回调中,将指针强制转换回正确的指针类型。
  • 取消引用指针并阅读内容。

这种方法是可重入的,因为每个线程都有自己的变量。