练习在同一个参数上同时使用线程

Practice using threads simultaneously on same argument


我正在练习C语言中多线程的使用(Linux OS)。我写了一个简单的代码来找到一个数字的约数,如果这个数字没有约数(不包括 1 和数字本身)那么它就是一个素数。
find_div 函数在循环中检查线程创建时 运行 的数字是否有除数。
我的问题是两个线程分别 运行ning。我试过拆分号码,但显然该方法删除了选项(因为发送的号码不是原始号码)。还尝试为循环使用全局索引 运行(认为每个线程在递增时都会使用“新”索引,但由于同步问题而无法正常工作)。
我不知道如何继续,希望得到关于我应该如何推进的提示和提示(或者是否有办法使全局索引方法起作用?)。
代码:

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

int prime, i;

void *find_div(void *f);

void main(int argc, char* argv[]){
    if(argc < 2){
        fprintf(stderr, "Must enter one number\n");
        exit(1);
    }

    int n;
    pthread_t thread[2];

    prime = 0; //Initialize
    n = atoi(argv[1]);

    if((pthread_create(&thread[0], NULL, find_div, (void *)n)) != 0){
        perror("thread");
        exit(1);
    }

    if((pthread_create(&thread[1], NULL, find_div, (void *)n)) != 0){
        perror("thread");
        exit(1);
    }

    pthread_join(thread[0], NULL);
    pthread_join(thread[1], NULL);

    if(prime == 0)
        fprintf(stdout, "%d is prime number\n", n);
    else
        fprintf(stdout, "\n");
}

void *find_div(void *f){
    for (i=2; i<(int)f; i++){ //Start from 2 since 1 is a divisor to all Natural numbers (and every Natural number is a divisor to itself)
        if ((int)f%i == 0){
            printf("%d ", i);
            prime = 1; //Meaning not prime number
        }
    }
}

数字为6时的输出:

2 3 2 3

你可以这样实现。将两个参数而不是一个参数传递给 find_div 函数。第二个参数应该是线程号。为此,您可以使用数组 int param[2],其中 param[0] 将具有 n,而 param[1] 将具有线程编号。然后 find_div可以这样实现:

void *find_div(void *f){

    int num = ((int*)f)[0];
    int tid = ((int*)f)[1];
    int start, end;

    if(tid == 0)
    {
        start = 2;
        end = num/2;
    }
    else
    {
        start = num/2;
        end = num;
    }

    for (i=start; i<end; i++){ //Start from 2 since 1 is a divisor to all Natural numbers (and every Natural number is a divisor to itself)

        if (num%i == 0){

            printf("%d ", i);

            prime = 1; //Meaning not prime number

        }

    }

}

更新

根据您的推荐和原始代码,我相信您需要了解线程参数类型void *。在您的代码中,int n; 被传递为 (void *)n 它起作用是因为指针与 int 的大小相同,但这不是正确的方法。正确的方法是传递 (void *)&n 并在线程函数内部将其用作 *(int*)f。让我演示如何传递结构并使用它。

void *find_div(void *f);

struct MyData {
  int num;
  char chr;
};

void main(int argc, char* argv[]){

//... initial code 

    struct MyData data;
    data.num = 10;
    data.chr = 'a';
    pthread_t thread[2];

    if((pthread_create(&thread[0], NULL, find_div, (void *)&data)) != 0){
        perror("thread");
        exit(1);
    }

    //... rest of code
}

然后在你的线程函数中你可以使用这样的参数。

void *find_div(void *f){

    struct MyData *pData = ((MyData*)f);
    int tid = pData->num;
    char chrData = pData->chr;

// ... rest of the code
}

希望这会帮助你做你需要做的事情。

我已经尝试创建一个结构来包含需要根据收到的答案传递的参数 - 使用线程 ID 没有成功。但是这个方法让我知道了如何解决这个问题(虽然这不是一个理想的方法):

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

int prime = 0, divisor = 0;

void *find_div1(void *s);
void *find_div2(void *s);

void main(int argc, char* argv[]){
    if(argc < 2){
        fprintf(stderr, "Must enter one number\n");
        exit(1);
    }
    
    int n;
    pthread_t thread[2];
    n = atoi(argv[1]);

    if((pthread_create(&thread[0], NULL, find_div1, (void *)n)) != 0){
        perror("thread");
        exit(1);
    }

    if((pthread_create(&thread[1], NULL, find_div2, (void *)n)) != 0){
        perror("thread");
        exit(1);
    }

    pthread_join(thread[0], NULL);
    pthread_join(thread[1], NULL); //Wait for both threads to finish

    if(prime == 0)
        fprintf(stdout, "%d is prime number\n", n);
    else
        fprintf(stdout, "\n");
}

void *find_div1(void *s){
    int num = (int)s;
    int start, end, i;
    
    if(num < 4)
        return;

    start = 2;
    end = num/2;

    for (i=start; i<end; i++){ 
        if (num%i == 0){
            if(divisor == 0){
                divisor = 1;
                fprintf(stdout, "Divisors of %d:\n", num);
            }
            printf("%d\n", i);
            prime = 1; //Meaning not prime number
        }
    }
}

void *find_div2(void *s){
    int num = (int)s;
    int start, end, i;

    if(num < 4)
        return;

    start = num/2;
    end = num;

    for (i=start; i<end; i++){ 
        if (num%i == 0){
            if(divisor == 0){
                divisor = 1;
                fprintf(stdout, "Divisors of %d:\n", num);
            }
            printf("%d\n", i);
            prime = 1; 
        }
    }
}

编辑:
这是答案后的代码:

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

int prime = 0, divisor = 0;

void *find_div(void *s);

struct my_args{
    int num;
    char id; //Will identify the thread running
};

void main(int argc, char* argv[]){
    if(argc < 2){
        fprintf(stderr, "Must enter one number\n");
        exit(1);
    }
    
    struct my_args arg1, arg2;

    arg1.num = atoi(argv[1]);
    arg1.id = 'a';
    arg2.num = atoi(argv[1]);
    arg2.id = 'b';

    pthread_t thread[2];

    if((pthread_create(&thread[0], NULL, find_div, (void *)&arg1)) != 0){
        perror("thread");
        exit(1);
    }

    if((pthread_create(&thread[1], NULL, find_div, (void *)&arg2)) != 0){
        perror("thread");
        exit(1);
    }

    pthread_join(thread[0], NULL);
    pthread_join(thread[1], NULL); //Wait for both threads to finish

    if(prime == 0)
        fprintf(stdout, "%d is prime number\n", atoi(argv[1]));
    else
        fprintf(stdout, "\n");
}

void *find_div(void *s){
    struct my_args *pArg = (struct my_args *)s;
    int num = pArg->num;
    char tid = pArg->id;

    int start, end, i;

    if(tid == 'a'){
        start = 2;
        end = num/2;
    }
    else{
        start = num/2;
        end = num;
    }

    for (i=start; i<end; i++){ //Start from 2 since 1 is a divisor to all Natural numbers (and every Natural number is a divisor to itself)
        if (num%i == 0){
            if(divisor == 0){
                fprintf(stdout, "Divisors of %d:\n", num);
                divisor = 1;
            }
            printf("%d\n", i);
            prime = 1; //Meaning not prime number
        }
    }
}