使用pthread_mutex_lock时遇到问题

3

我刚开始在大学里学习一些关于线程的知识,但似乎还没有完全理解。

我的代码想要获取参数并检查它们是否为偶数或质数,如果是则输出。此外,还要计算每种类型数字的总和。

以下是代码:

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

#define something 10

pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
int snrp=0;
int sprim=0;

void * verif(void* argv){
    pthread_mutex_lock(&lock);
    int x=*(int*)argv;
    if (x%2==0){
        printf("%d is even\n",x);
        snrp+=x;
    }
    else{
        int ok=1;
        int d;
        if(x<1)
            ok=0;
        for(d=3;d*d<x;d+=2)
            if(x%d==0)
                ok=0;
        if(ok==0)
            return NULL;
        printf("%d is prime\n",x);
        sprim+=x;
    }
    pthread_mutex_unlock(&lock);
    sleep(1);
    return NULL;
}


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

    pthread_t threads[something];
    int i,n;
    for(i=1;i<argc;i+=1){
        n=atoi(argv[i]);
        if(pthread_create(&threads[i],NULL,verif,(void*) &n))
            printf("Error");
    }
    for(i=1;i<argc;i+=1)
        pthread_join(threads[i],NULL);

    printf("Even numbers sum is %d \n",snrp);
    printf("Prime numbers sum is %d \n",sprim);
    pthread_mutex_destroy(&lock);
    return 0;

}

如果我使用例如参数 2,3,5,则输出为:
5 is prime
5 is prime
5 is prime
Even numbers sum is 0 
Prime numbers sum is 15 

有人能解释一下为什么吗?

3个回答

1

@Darkmer

void * verif(void* argv){ pthread_mutex_lock(&lock); int x=*(int*)argv; printf("%p存储了%d",argv,n); // 在你的代码中添加这一行。

你会明白,每次都发送相同的地址,因此相同的n(在你的样例中为5)。为什么会发生这种情况?那是因为在线程使用n之前,你在主函数中并行地用下一个命令行参数改变了它。

这发生了,因为在主程序中,你对所有三个参数使用了相同的“n”。相反,延迟使用atoi函数,并在verif()中使用它。直接从命令行参数传递argv。我可以为你更改pthread_create(..)函数,但那是你的家庭作业。

祝好运。


确实,你是对的,在我修改了pthread_create()参数并在verif()函数中使用了atoi()之后,程序按照预期运行。谢谢。 - Darkmer

1

你的 verif 函数可能在这里返回而不释放锁:

if(ok==0)
     return NULL;

我将永久锁定该锁,任何试图获取它的线程都将永远等待。

此外,这是错误的:

for(i=1;i<argc;i+=1){
n=atoi(argv[i]);
if(pthread_create(&threads[i],NULL,verif,(void*) &n))
    printf("Error");
}

你将线程的地址传递给了n,但它应该如何处理这个地址呢?在此代码中,n的值被修改且没有同步,因此新线程无法合法地访问它。不要传递线程n的地址,而是传递n

我已经删除了那部分,而是在结尾处检查ok==1以继续。再次得到3X 5是质数/偶数和=0/质数和=15。 - Darkmer
你还有很多漏洞需要修复。我添加了一个更新。在你的代码中,n被第一个线程和新线程共享,但没有同步。 - David Schwartz
好的,我明白了,但我不太确定我该如何做到这一点。 一般来说,我对C语言还很陌生。在学校里我知道我需要使用void*来传递参数。我尝试了很多不同的方法来发送实际值,但是每次都会出现另一个警告/错误。你知道有什么好的研究资料可以帮助解决我的问题吗? - Darkmer

1
您为线程发送了相同的参数。
int main(int argc,char* argv[]){

    pthread_t threads[something];
    int i;
    int n[3] = {2, 3, 5};
    for(i=0;i<3;i+=1)
    {
        if(pthread_create(&threads[i],NULL,verif,(void*) &n[i]))
            printf("Error");
    }
    for(i=0;i<3;i+=1)
        pthread_join(threads[i],NULL);

    printf("Even numbers sum is %d \n",snrp);
    printf("Prime numbers sum is %d \n",sprim);
    pthread_mutex_destroy(&lock);
    return 0;

}

注意: pthread_create(&threads[i],NULL,verif,(void*) &n[i])

这里是链接: http://linux.die.net/man/3/pthread_create


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接