3

I just started at college to study a little bit about threads, and it seems that I don't quite get the hang of it.

I wanted for my code to get the arguments and check if they are either even or prime numbers, and if they are, to print them. Additionally make the sum of each one of these kind of numbers.

This is the code:

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

}

If I use for example the arguments 2,3,5 I get the output:

5 is prime
5 is prime
5 is prime
Even numbers sum is 0 
Prime numbers sum is 15 

Can someone please explain why?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Darkmer
  • 45
  • 3

3 Answers3

1

Your verif function can return without releasing the lock here:

if(ok==0)
     return NULL;

That will leave the lock held forever and any other thread that tries to acquire it will wait forever.

Also, this is wrong:

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

You pass the thread the address of n, but what is it supposed to do with that address? The value of n is modified in this code with no synchronization, so the new thread cannot legally access it. Instead of passing the thread the address of n, pass it the value of n.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • i have removed that part, instead just checked at the end if ok==1 to continue. Again i get 3X 5 is prime / even sum=0/ prime sum=15 – Darkmer May 15 '16 at 05:18
  • You have lots more bugs to fix. I updated with another. In your code, `n` is shared between the first thread and the new threads but there's no synchronization. – David Schwartz May 15 '16 at 05:20
  • Ok, got that, but I'm not really sure how i can do that, i am new to c language in general. I understood at college i need to use void* for passing arguments. I tried different ways to send the actual value, but for each way i got another warning/ error. Do you know some good research material for my problem? – Darkmer May 15 '16 at 05:36
1

@Darkmer

void * verif(void* argv){ pthread_mutex_lock(&lock); int x=*(int*)argv; printf("%p stores %d",argv,n); // Add this line. in your code.

You will understand, every time you are sending same address, thus same n ( which is 5 in your sample). Why this happened? that happened because before the thread used n, you parallely changed it in main function with next command line argument.

This happened, because in main program, you used same 'n' for all three parameters. Instead, postpone the atoi function and use it inside verif(). pass argv directly from command line arguments. I can do that pthread_create(..) function change for you, but that is your home work.

good luck.

Jay Kumar R
  • 537
  • 2
  • 7
  • Indeed, you were right, the program runs as it was intended after i modified the pthread_create() argument and used atoi() in the verif() function. Thanks – Darkmer May 15 '16 at 05:54
1

You send the same parameter for your thread.

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;

}

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

Here is the link: http://linux.die.net/man/3/pthread_create

BlackMamba
  • 10,054
  • 7
  • 44
  • 67