【问题标题】:Passing threads a value from a for loop向线程传递来自 for 循环的值
【发布时间】:2018-10-09 02:35:50
【问题描述】:

我正在尝试创建线程并将来自 for 循环的值传递给每个线程。这是代码段

pthread_t *threadIDs;
    int i = 0;
    if(impl == 1)
    {
        threadIDs = (pthread_t *)malloc(sizeof(pthread_t)*reduces);
        for(;i < reduces; i++)
        {
            pthread_create(&threadIDs[i], NULL, reduce,&i);
        }
    }

它没有传递正确的循环值,这是有道理的,因为我正在创建一个竞争条件。从循环中传递 i 的正确值的最简单方法是什么?

另一个问题,每个线程会在下一个线程被创建和调用之前完成执行吗?

【问题讨论】:

  • 像使用 phtread_t 一样分配一个 int 可能是一个解决方案。
  • @u__:肯定有!将相同的地址传递给每个线程,尽管它指向的值在创建新线程之前已更改。
  • 哦,是的.. 感谢您的纠正

标签: c multithreading loops


【解决方案1】:

您已经动态创建了一个线程 ID 数组。对要传入的值执行相同操作。

pthread_t *threadIDs;
int *values;
int i = 0;
if(impl == 1)
{
    threadIDs = malloc(sizeof(pthread_t)*reduces);
    values = malloc(sizeof(int)*reduces);
    for(;i < reduces; i++)
    {
        values[i] = i;
        pthread_create(&threadIDs[i], NULL, reduce, &values[i]);
    }
}

每个线程将使用不同的数组成员,因此不存在竞争条件。

【讨论】:

  • 我添加了这个,但是,当我打印在 reduce(void*) 方法中获得的索引时,我以错误的顺序从 0-3 获取值,我应该得到 0- 10 以正确的顺序。创建线程时我做错了吗?
  • 以错误的顺序打印更多地与您的 i/o 是否缓冲有关(如果它的 printf 系列调用不相信输出)、线程调度等等..
  • 这能解释为什么我没有得到我期望的全部数字吗?我应该得到 0-10,但我只得到 0-3 @u__
  • 也许......如果你的主线程在缓冲区被刷新之前退出,你可能根本看不到输出。在主线程中的 for 循环之后给几秒钟的睡眠,看看.. 或 pthread_join
  • @u__ 是的,就是这样。我添加了一个 sleep(1) 并按预期打印出所有内容。谢谢
【解决方案2】:

您可以定义一个结构并将 i 分配给对象的变量。

#include <stdio.h>
#include <pthread.h>

typedef struct Param_ {
    int index;
}Param;

static void* thread(void* p) {
    Param* param = p;
    printf("index: %d\n", param->index);
}

int main() {
    int i = 0;
    int reduces = 10;
    pthread_t *threadIDs;

    threadIDs = (pthread_t *)malloc(sizeof(pthread_t)*reduces);
    for(; i < reduces; i++)
    {
        Param* p;
        p = (Param*)malloc(sizeof(*p));
        p->index = i;
        pthread_create(&threadIDs[i], NULL, thread, p);
    }

    return 0;
}

【讨论】:

    【解决方案3】:

    从我的循环中传递 i 的正确值的最简单方法是什么?

    什么被认为是“简单”取决于用例,所以这里有另一种方法来解决您提出的问题:

    #include <pthread.h>
    
    pthread_mutex_t m_init;
    pthread_cond_t c_init;
    
    int init_done = 1;
    
    void* thread_function(void * pv)
    {
      pthread_mutex_lock(&m_init);
    
      size_t i = *((size_t*) pv);
      init_done = 1;
    
      pthread_cond_signal(&c_init);
    
      pthread_mutex_unlock(&m_init);
    
      ...
    }
    
    #define THREADS_MAX (42)
    
    int main(void)
    {
      pthread_t thread[THREADS_MAX];
    
      pthread_mutex_init(&m_init, NULL);
      pthread_cond_init(&c_init, NULL);
    
      for(size_t i = 0; i < THREADS_MAX; ++i)
      {
        pthread_mutex_lock(&m_init);
    
        init_done = 0;
        pthread_create(&thread[i], NULL, thread_function, &i);
    
        while (!init_done)
        {
          pthread_cond_wait(&c_init);
        }
    
        pthread_mutex_unlock(&m_init);
      }
    
      ...
    }
    

    (为了便于阅读,省略了错误检查)

    【讨论】:

    • 在未被 callng 线程锁定的互斥体上调用 pthread_mutex_unlock()undefined behavior or an error,具体取决于互斥体的类型。
    • @AndrewHenle:谢谢。我知道我的 PThreads 生锈了。修好了吗?
    • 在这种情况下可能更容易让子线程调用sem_post(),而父线程调用sem_wait()
    猜你喜欢
    • 2022-12-06
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多