【问题标题】:Trouble using pthread_mutex_lock使用 pthread_mutex_lock 时遇到问题
【发布时间】:2017-08-03 21:36:42
【问题描述】:

我刚开始在大学学习一点关于线程的知识,但我似乎不太了解它。

我想让我的代码获取参数并检查它们是偶数还是质数,如果是,则打印它们。此外,将这些数字中的每一种相加。

这是代码:

#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 

谁能解释一下原因?

【问题讨论】:

    标签: c linux pthreads


    【解决方案1】:

    @Darkmer

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

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

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

    祝你好运。

    【讨论】:

    • 确实,您是对的,在我修改 pthread_create() 参数并在 verif() 函数中使用 atoi() 后,程序按预期运行。谢谢
    【解决方案2】:

    您的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
    • 您还有很多错误需要修复。我更新了另一个。在您的代码中,n 在第一个线程和新线程之间共享,但没有同步。
    • 好的,明白了,但我不太确定我怎么能做到这一点,我一般是 c 语言的新手。我在大学里明白我需要使用 void* 来传递参数。我尝试了不同的方式来发送实际值,但是对于每种方式,我都会收到另一个警告/错误。你知道一些很好的研究材料来解决我的问题吗?
    【解决方案3】:

    您为您的线程发送相同的参数。

    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(&amp;threads[i],NULL,verif,(void*) &amp;n[i])

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-21
      • 2021-11-08
      • 2014-01-08
      • 2011-03-09
      • 2013-01-30
      • 2016-11-13
      • 2016-07-21
      相关资源
      最近更新 更多