2012-10-01 26 views
0

我想製作一個程序,計算某些數字之間的素數。 我做了一個循環隊列來保存素數。 所以基本上,2個線程在循環隊列中找到素數併入隊,並且線程取出素數並對它們進行計數。我的代碼中使用了 ,get_prime()和get_prime2()做了入隊的事情,而consumer()做了取出的事情。 問題是,它不能正確計算素數。我認爲,在進行中,即使隊列已滿,排隊線程中的一個線程會嘗試將質數放入隊列中,以便素數不會放入隊列中並且會被忽略。C pthread編程(計數素數)使用mutex_lock,cond_wait

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

//queue size 
#define QUEUESIZE 1 

//a node in a queue 
typedef struct queue{ 
    int element[QUEUESIZE+1]; 
    int front; 
    int rear; 
    int count; 
}queue; 

//make a queue 
queue q; 

pthread_mutex_t mutex_lock; 
pthread_cond_t p_cond = PTHREAD_COND_INITIALIZER; 
pthread_cond_t c_cond = PTHREAD_COND_INITIALIZER; 

//prime count 
int count=0; 

//prototype 
void init_queue(queue *q); 
int enqueue(queue *q, int x); 
int dequeue(queue *q); 
int q_empty(queue *q); 
int q_full(queue *q); 
void *get_prime(); 
void *get_prime2(); 
void *consumer(); 

int main(int argc, const char * argv[]) 
{ 
    pthread_t p_thread[2]; //producer thread 
    pthread_t c_thread; //consumer thread 
    int status; 

    init_queue(&q); 

    pthread_mutex_init(&mutex_lock, NULL); 
    pthread_cond_init(&p_cond, NULL); 
    pthread_cond_init(&c_cond, NULL); 
    pthread_create(&p_thread[0], NULL, get_prime, (void*)NULL); 
    pthread_create(&p_thread[1], NULL, get_prime2, (void*)NULL); 
    pthread_create(&c_thread, NULL, consumer, (void*)NULL); 
    pthread_join(p_thread[0], (void **)&status); 
    pthread_join(p_thread[1], (void **)&status); 
    pthread_join(c_thread, (void **)&status); 

    printf("\nThe number of prime numbers between 1~100000: %d\n", count); 

    return 0; 
} 

//queue initialization 
void init_queue(queue *q) 
{ 
    q->front = 0; 
    q->rear = QUEUESIZE-1; 
    q->count = 0; 
} 

int enqueue(queue *q, int x) 
{ 
    if(q_full(q)) 
    { 
     return -1; 
    } 
    else{ 
     q->rear = (q->rear+1) % QUEUESIZE; 
     q->element[q->rear] = x; 
     q->count = q->count + 1; 
     return 0; 
    } 
} 

int dequeue(queue *q) 
{ 
int x; 

if(q_empty(q)) 
{ 
    return -1; 
} 
else 
{ 
    x = q->element[q->front]; 
    q->front = (q->front+1) % QUEUESIZE; 
    q->count = q->count - 1; 
} 

return x; 
} 

int q_empty(queue *q) 
{ 
if(q->count <= 0) 
    return 1; 
else 
    return 0; 
} 

int q_full(queue *q) 
{ 
if(q->count >=QUEUESIZE) 
    return 1; 
else 
    return 0; 
} 

void *get_prime() 
{ 
int i, j; //loop counter 
int temp = 0; 

for(i=2; i<50; i++) 
{ 
    for(j=2; j<=sqrt(i); j++) 
    { 
     if(i%j==0){ 
      temp++; 
      break; 
     } 
    } 
    if(temp==0) 
    { 
     pthread_mutex_lock(&mutex_lock); 

     if(enqueue(&q, i)==-1) //queue full condition 
     { 
      pthread_cond_wait(&p_cond, &mutex_lock); 
      enqueue(&q, i); 
      printf("%d\t", i); 
     } 
     else 
      printf("%d\t", i); 
     pthread_cond_signal(&c_cond); 

     pthread_mutex_unlock(&mutex_lock); 
    } 
    temp=0; 
} 
} 
void *get_prime2() 
{ 
int i, j; //loop counter 
int temp = 0; 

for(i=50; i<100; i++) 
{ 
    for(j=2; j<=sqrt(i); j++) 
    { 
     if(i%j==0){ 
      temp++; 
      break; 
     } 
    } 
    if(temp==0) 
    { 
     pthread_mutex_lock(&mutex_lock); 

     if(enqueue(&q, i)==-1) //queue full condition 
     { 
      pthread_cond_wait(&p_cond, &mutex_lock); 
      enqueue(&q, i); 
      printf("%d\t", i); 
     } 
     else 
      printf("%d\t", i); 
     pthread_cond_signal(&c_cond); 

     pthread_mutex_unlock(&mutex_lock); 
    } 
    temp=0; 
} 
} 

void *consumer() 
{ 
int isempty; 

while(1) 
{ 
    pthread_mutex_lock(&mutex_lock); 
    isempty = dequeue(&q); 

    if(isempty != -1){ 
     count++; 
    } 
    else 
     pthread_cond_wait(&c_cond, &mutex_lock); 
    pthread_cond_signal(&p_cond); 
    pthread_mutex_unlock(&mutex_lock); 


    } 
} 
+0

爲什麼你清空隊列?如果一個數字在小於或等於數字平方根的所有素數之間沒有分隔符,那麼它是一個素數。 – Serge

+0

我知道了,但是我想看看pthread是如何去做的,所以不要只計算get_prime()中的數字,我要清空隊列來計算 –

+0

除非你這樣做才能學習,否則你不應該這麼做所有這些,因爲有一個非常快速的開源C++庫,可以爲你做到這一點:https://code.google.com/p/primesieve/ –

回答

1

,所以這是我的新修正的代碼,感謝

void *get_prime2() 
{ 
    int i, j; //loop counter 
    int temp = 0; 

    for(i=50000; i<100000; i++) 
    { 
     for(j=2; j<=sqrt(i); j++) 
     { 
      if(i%j==0){ 
       temp++; 
       break; 
      } 
     } 

     if(temp==0) 
     { 
      pthread_mutex_lock(&mutex_lock); 

      while(1) 
      { 
       if(enqueue(&q, i) == -1) 
        pthread_cond_wait(&p_cond, &mutex_lock); 
       else 
       { 
        break; 
       } 
      } 

      pthread_cond_signal(&c_cond); 
      pthread_mutex_unlock(&mutex_lock); 
     } 
     temp=0; 
    } 
} 

void *consumer() 
{ 
    int isempty; 

    while(1) 
    { 
     pthread_mutex_lock(&mutex_lock); 
     isempty = dequeue(&q); 

     if(isempty != -1){ 
      count++; 
     } else { 
      pthread_cond_wait(&c_cond, &mutex_lock); 
     } 

     pthread_cond_signal(&p_cond); 
     pthread_mutex_unlock(&mutex_lock); 
    } 
}