【问题标题】:Pass Struct with an array and Index to access to Thread传递带有数组和索引的 Struct 以访问 Thread
【发布时间】:2018-07-14 20:01:32
【问题描述】:

对于素数分解项目,我需要将一个结构和一个数字(从命令行)传递给一个线程。下面的代码是我到目前为止所拥有的。分解工作正常,问题是传递给线程的索引没有按顺序传递,因此结果会有所不同,通常将数据存储在后续线程的同一索引中。任何人都知道如何保证线程将访问哪个索引,或者更好的实现方式?每个线程都必须将其数据存储在一个结构中,以便在所有线程关闭后,主线程可以在最后打印所有数据。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

// Initialize Constants
#define MAX_ARGS 25
#define MAX_PRIMES 10
#define SMALLEST_ARG 2

// Define Struct
struct PrimeData {
    int index;
    int num_to_fact[MAX_ARGS];
    int primes[MAX_ARGS][MAX_PRIMES];
};

// Declare Functions
void* factor (void*);

// Main
int main(int argc, char* argv[])
{
    // Initialize Struct Variables
    struct PrimeData data;
    struct PrimeData* data_addr = &data;
    data.index = 0;
    for (int i = 0; i < MAX_ARGS; i++)
        data.num_to_fact[i] = -1;
    for (int i = 0; i < MAX_ARGS; i++) {
        for (int j = 0; j < MAX_PRIMES; j++)
            data.primes[i][j] = -1;
    }

    // Check for arguments
    if (argc <= 1)
        printf("Usage: ./p3 <number to factor>...\n");
    else {
        // Initialize Thread Handler list
        pthread_t threads[argc - 1];

        // Create a Thread per Argument
        for (int i = 1; i < argc; i++) {
            // Update shares structure
            data.index = i - 1;
            data.num_to_fact[i - 1] = atoi(argv[i]);            

            // Create thread
            pthread_create(&threads[i - 1], NULL, factor, (void*)data_addr);
        }

        // Tell main to wait for threads to terminate
        for (int i = 1; i < argc; i++)
            pthread_join(threads[i - 1], NULL);
    }

    // Iterate through struct
    for (int i = 0; i < MAX_ARGS; i++) {
        if (data.num_to_fact[i] == -1)
            break;
        printf("%d: ", data.num_to_fact[i]);
        for (int j = 0; j < MAX_PRIMES; j++) {
            if (data.primes[i][j] == -1)
                break;
            printf("%d ", data.primes[i][j]);
        }
        printf("\n");
    }

    // Terminate
    return 0;
}

// The factor() function
void* factor(void* data)
{
    struct PrimeData* d = (struct PrimeData*)data;
    int index = d->index;
    int n = d->num_to_fact[index];
    int counter = 0;
    int i = 2;
    while (n != 1) {
        if (n % i == 0) {
            while (n % i == 0) {
                d->primes[index][counter] = i;
                n = n / i;
                counter++;
            }
        }
        i++;
    }
    return NULL;
}

【问题讨论】:

  • 线程不仅仅是一个函数,它有它自己的执行上下文,它不受你的主函数的控制。这意味着您正在多次运行功能因素,而没有特定的开始和结束顺序。当您为每个参数创建一个线程并更改每个线程需要使用的参考数据内容(索引)时,您也会给那些需要访问数据内容的线程带来问题。

标签: c multithreading


【解决方案1】:

您只有一个 'struct PrimeData data;',因此在 pthread_create 调用中发信号通知它的地址是没有意义的。混乱的方法是全球化'PrimeData'以便线程可以访问它,数组化索引:'int index [MAX_ARGS];',用0,1,2,3 ..等加载它,然后传递每个线程所需索引的地址,例如'&data_addr[i-1]'。

如果您接受 C 数组从零开始索引并去掉很多 [i-1] 的东西,可能会更清楚。

【讨论】:

  • 问题是线程还需要从命令行给出一个数字。第一个参数是通用调用,来自用户的所有后续参数都以 1 开头,因此是 i-1 等等。基本上,每个线程都需要一个来自命令行的数字,然后将该数字加上主要因素存储到一个结构中,然后主线程将所有信息打印出来。我知道如何将结构传递给线程,但是,如果我传递结构,那么我无法从命令行传递参数。除非我先将它放入结构中,除非有办法同时通过。
【解决方案2】:

我使用互斥锁让它工作。有点奇怪,直到下一章我们才会介绍互斥锁。我最终偶然发现了一篇文章,解释说当您使用多线程时,每个线程都在访问共享内存位置(在这种情况下是我的结构),那么您必须使用互斥锁来控制索引:

// At the start of the program, before main
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int _index = -1;

// first three lines of the factor function
pthread_mutex_lock(&mutex1);
_index++;
pthread_mutex_unlock(&mutex1);

【讨论】:

    【解决方案3】:
    // Define Struct
    struct PrimeData {
        int num_to_fact[MAX_ARGS];
        int primes[MAX_ARGS][MAX_PRIMES];
    };
    
    typedef struct Wrapper {
        int index;
        struct PrimeData *data;
    } Wrapper;
    
    ...
    
    int main(int argc, char *argv)
    {
        // ...
        // Define wrappers
        Wrapper wrappers[argc-1];
    
        for (int i = 1; i < argc; i++)
        {
            wrappers[i-1].index = i;
            wrappers[i-1].data = &data;
            //...
            pthread_create(&threads[i - 1], NULL, factor, wrappers + i - 1);
        }
        // ...
    }
    
    void *factor(void *wrapper)
    {
        Wrapper *w = (Wrapper *) wrapper;
        struct PrimeData* d = w->data;
        int index = w->index;   
        // ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-20
      • 1970-01-01
      • 2023-03-18
      • 2021-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多