使用mutex_lock,cond_wait进行C pthread编程(计算素数)

时间:2012-10-01 17:25:31

标签: c pthreads

我想制作一个计算某些数字之间的素数的程序。 我做了一个循环队列来保存素数。 所以基本上,2个线程找到素数并在循环队列中排队,并且 1个线程取出素数并计算它们。 从我的代码中,get_prime()和get_prime2()执行enqueue事务,而consumer()执行取出的操作。 问题是,它没有正确计算素数。我认为,在进行中,即使队列已满,其中一个排队线程会尝试将素数放入队列中,以便素数不会被放入队列中而且会丢失。

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


    }
}

1 个答案:

答案 0 :(得分: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);
    }
}