C生产者/消费者-输出相同的数据并在完成之前卡住

C生产者/消费者-输出相同的数据并在完成之前卡住,c,operating-system,semaphore,producer-consumer,C,Operating System,Semaphore,Producer Consumer,我们有一个基于生产者/消费者问题的任务。从本质上讲,任务归结为: 让N_PROD,N_CON分别表示创建的生产者/消费者线程的数量,让BUF_SIZE表示缓冲区的大小 每个生产者线程必须选择2个随机素数,将它们相乘,然后将结果添加到缓冲区 让TOTAL_PRIMES表示从缓冲区添加或删除元素的次数。显然,一些线程可能会比其他线程更多地访问缓冲区(例如,如果TOTAL_PRIMES=5和N_PROD=3,那么如果producer1向缓冲区添加三种不同的产品,producer2添加两种,而prod

我们有一个基于生产者/消费者问题的任务。从本质上讲,任务归结为:

  • N_PROD,N_CON
    分别表示创建的生产者/消费者线程的数量,让
    BUF_SIZE
    表示缓冲区的大小

  • 每个生产者线程必须选择2个随机素数,将它们相乘,然后将结果添加到缓冲区

  • TOTAL_PRIMES
    表示从缓冲区添加或删除元素的次数。显然,一些线程可能会比其他线程更多地访问缓冲区(例如,如果
    TOTAL_PRIMES=5
    N_PROD=3
    ,那么如果
    producer1
    向缓冲区添加三种不同的产品,
    producer2
    添加两种,而
    producer3
    不添加任何产品,那么就完全可以了)

  • 生成的线程应该只在主线程创建了所有生产者/消费者之后才开始工作

不过,每次我执行这个程序时,它似乎都不会超过3或4个主要产品。此外,它似乎一直在写同样的数据

我的主要问题是,为什么这个项目一直没有结束?我似乎不知道它卡在哪里了。我不知道重复的数据是第一个问题的结果,还是两个独立的问题

以下是我认为与我的代码最相关的部分(因此不包括任何只进行一些计算或向控制台输出内容的函数):

Output2.txt

Output3.txt

Output4.txt


p_计数和c_计数是简单的全局变量,不受竞争条件的保护。应以线程安全的方式处理这两个计数器。变量pdone和cdone是不必要的。生产者线程和消费者线程可以退出,其中这些int被赋值为1。线程循环应该是无限循环,直到调用pthread_exit()为止。请记住,总的_素数包括缓冲区元素写入缓冲区的次数加上缓冲区元素从缓冲区读取的次数。使用者必须等待一个或多个生产者填充缓冲区,然后才能使用元素。这意味着生产者应该生产比消费者消费更多的元素。
// Declaration of thread condition variable 
pthread_cond_t start_cond = PTHREAD_COND_INITIALIZER; 
// declaring mutex 
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 

lluint buf[BUF_SIZE];

int p_count = 0;
int c_count = 0;
int all_started = 0;
int pdone = 0;
int cdone = 0;

//////////////////////////////////
sem_t* sem_access;
sem_t* sem_occupy;  //how many elements currently in buffer
sem_t* sem_free;    //how much free space we have
sem_t* sem_all_started;

sem_t* sem_buf;

///////////////////////////////////////////

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

    pthread_t p_threads[N_PROD];
    pthread_t c_threads[N_CONS];

    open_all_sem(); //helper function to opens all semaphores listed above

    int rc, t;
    for (t=0; t<N_PROD; t++)
    {
        rc = pthread_create(&p_threads[t], NULL, producer, (void*)t);
        if (rc)
        {
          printf("ERROR; return code from pthread_create() is %d\n", rc);
          exit(-1);
       }
    }


    sem_wait(sem_access);   
    printf("main thread created all producer threads\n");   
    sem_post(sem_access);   

    for (t=0; t<N_CONS; t++)
    { 
        rc = pthread_create(&c_threads[t], NULL, consumer, (void*)t);
        if (rc)
        {
          printf("ERROR; return code from pthread_create() is %d\n", rc);
          exit(-1);
       }
    }

    printf("main thread created all consumer threads\n");   
    broadcast_all_started();

    for (t=0; t<N_PROD; t++)
    {
        rc = pthread_join(p_threads[t], NULL);
        if (rc != 0)
        {
            printf("Error joining producer thread %d\n", t+1);
            exit(-1);
        }
    }

    for (t=0; t<N_CONS; t++)
    {
        rc = pthread_join(c_threads[t], NULL);
        if (rc != 0)
        {
            printf("Error joining consumer thread %d\n", t+1);
            exit(-1);
        }

    }

    printf("Back in main thread\n");

    sem_unlink("/sem_free");
    sem_unlink("/sem_access"); 
    sem_unlink("/sem_occupy");
    sem_unlink("/sem_all_started");
    sem_unlink("/sem_buf");

    printf("Goodbye!\n");
    close_Semaphors();
    return 0;
}



void producer(void* id)
{
    wait_in_threads_until_all_start();
    int p_id = (int)id + 1;

    while (!pdone)
    {
        lluint prime1, prime2, primeProd;

        prime1 = getPrimeNum();  
        prime2 = getPrimeNum();
        primeProd = prime1 * prime2;


        sem_wait(sem_free); 
        sem_wait(sem_access);   
        write_add_to_buf_msg(p_id, prime1, prime2, primeProd);   
        write_producer_is_done(p_id);  //simply outputs something 
        sem_post(sem_access);
        sem_post(sem_occupy);   

        p_count++;
        if (p_count == TOTAL_MSG)
        {
            printf("all producers terminated\n");
            pdone = 1;
        }
    }

    if (pdone == 1)
        pthread_exit(NULL);
}


void add_to_buf (lluint prod)
{

    sem_wait(sem_buf);
    int val;
    sem_getvalue(sem_occupy, &val);

    buf[val] = prod;
    sem_post(sem_buf);      
}


void consumer(void* id)
{
    wait_in_threads_until_all_start();
    int c_id = (int)id+1;

    while (!cdone)
    {       
        sem_wait(sem_occupy);

        lluint prod, factor1, factor2;      
        sem_wait(sem_access);   
        write_remove_from_buf_msg(c_id, &prod); //within this we call remove_from_buf
        find_two_factors(prod, &factor1, &factor2);     
        printf(" = %lli x %lli\n", factor1, factor2);
        write_consumer_is_done(c_id);
        sem_post(sem_access);   
        sem_post(sem_free);
        c_count++;  

        if (c_count == TOTAL_MSG)
        {
            printf("all consumers terminated\n");
            cdone = 1;
        }
    }
    if (cdone == 1)
        pthread_exit(NULL);

}


void remove_from_buf(lluint* prod)
{
    sem_wait(sem_buf);   

    int val;
    sem_getvalue(sem_occupy, &val);

    *prod = buf[val];
    sem_post(sem_buf);   
}


void wait_in_threads_until_all_start()
{
    sem_post(sem_all_started);
    pthread_mutex_lock(&lock);
    if (all_started == 0)
    {
        pthread_cond_wait(&start_cond, &lock); 
    }
    pthread_mutex_unlock(&lock);
}


void all_threads_ready()
{
    pthread_mutex_lock(&lock);
    all_started = 1;
    pthread_cond_broadcast(&start_cond);
    pthread_mutex_unlock(&lock);
}



void close_Semaphors(void)
{
    sem_close(sem_access);
    sem_close(sem_occupy);
    sem_close(sem_free);
    sem_close(sem_all_started);
    sem_close(sem_buf);
}
main thread created all producer threads
main thread created all consumer threads
producer #1 going to add product: 15347 = 103 x 149
producer #1 is done
producer #2 going to add product: 15347 = 103 x 149
producer #2 is done
consumer #3 just removed: 15347 = 103 x 149
consumer #3 is done
consumer #1 just removed: 15347 = 103 x 149
consumer #1 is done
producer #1 going to add product: 19367 = 107 x 181
producer #1 
main thread created all producer threads
main thread created all consumer threads
producer #1 going to add product: 15347 = 103 x 149
producer #1 
main thread created all producer threads
main thread created all consumer threads
producer #1 going to add product: 15347 = 103 x 149
producer #1 is done
consumer #3 just removed: 15347 = 103 x 149
consumer #3 is done
producer #1 going to add product: 19367 = 107 x 181
producer #1 is done
consumer #2 just removed: 19367 = 107 x 181
consumer #2 is done
producer #1 going to add product: 27221 = 163 x 167
producer #1 is done
consumer #1 just removed: 27221 = 163 x 167
consumer #1 
main thread created all producer threads
main thread created all consumer threads
producer #1 going to add product: 15347 = 103 x 149
producer #1 is done
consumer #3 just removed: 15347 = 103 x 149
consumer #3 is done
producer #1 going to add product: 19367 = 107 x 181
producer #1 is done
consumer #1 just removed: 19367 = 107 x 181
consumer #1 is done
producer #1 going to add product: 27221 = 163 x 167
producer #1 is done
consumer #2 just removed: 27221 = 163 x 167
consumer #2 is done
producer #1 going to add product: 20651 = 107 x 193
producer #1 is done
consumer #3 just removed: 20651 = 107 x 193
consumer #3 is done
producer #1 going to add product: 30967 = 173 x 179
producer #1 is done
consumer #1 just removed: 30967 = 173 x 179
consumer #1