将结构和数组传递给索引以访问线程

时间:2018-07-14 20:01:32

标签: c multithreading

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

#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;
}

3 个答案:

答案 0 :(得分:0)

您只有一个“结构PrimeData数据;”,因此在pthread_create调用中发信号通知其地址毫无意义。混乱的方式是全球化“ PrimeData”,以便线程可以访问它,对索引进行数组化:“ int index [MAX_ARGS];”,将其加载为0、1、2、3等。然后通过每个线程所需索引的地址,例如'&data_addr [i-1]'。

如果您接受C数组从零开始索引,从而摆脱掉很多这些[i-1]事情,可能会更清楚。

答案 1 :(得分:0)

我使用互斥锁使它正常工作。有点奇怪,我们不会在下一章介绍互斥体。我最终偶然发现一篇文章,其中解释了当您使用多线程时,每个线程都在访问共享内存位置(在本例中为我的结构),那么您必须使用互斥锁控制索引:

// 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);

答案 2 :(得分:0)

// 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;   
    // ...
}