c - 如何防止一个线程递减信号量,直到另一个线程准备好为止?

标签 c pthreads semaphore

我正在循环内执行sem_post(),但它似乎并没有增加目标信号量的值。代码如下:

void* producerFunc(void* arg)
{
    int x, d, i, semValue, semTaken;

    sem_getvalue(&sem_posTaken, &semTaken);
    sem_getvalue(&sem_posAvaliable, &semValue);
    while(n_insertions < N_PRODUCTS)
    {
        sem_wait(&sem_posAvaliable);    //Verifica se tem espaço vazio no buffer
        sem_getvalue(&sem_posAvaliable, &semValue);
        x = produce_item();
        sem_wait(&db);
        insert_buffer(x);
        sem_post(&db);

        printf("n_insertions: %d\n", n_insertions);
        if(n_insertions % 5 == 0){
            sem_getvalue(&sem_posTaken, &semValue);
            for(i=0; i< Buffer_Size; i++)
            {
                sem_getvalue(&sem_posTaken, &semTaken);
                printf("VOU DAR POST %d\n", semTaken);
                sem_post(&sem_posTaken);   //Sinaliza para o consumidor que já tem item no buffer
                sem_getvalue(&sem_posTaken, &semTaken);
                printf("DEI POST %d\n", semTaken);
            }
        }
    }
    pthread_exit(NULL);
}

最初发布问题后,我将问题追溯到运行此代码的另一个线程的行为:

void* consumerFunc(void* arg)
{
    int d;
    struct sConsumer* cons = (struct sConsumer*) arg;
    while(n_consumed < N_PRODUCTS)
    {
        n_consumed++;
        sem_wait(&sem_posTaken); //Verifica se já tem item dentro do Buffer_Size
        sem_wait(&mutex);       //Garante acesso exclusivo
        consumers++;
        if(consumers == 1)
            sem_wait(&db);
        remove_buffer(cons->id);
        sem_getvalue(&sem_posTaken, &d);
        printf("Taken: %d\n", d);
        sem_post(&mutex);
        sem_post(&sem_posAvaliable);
        sem_wait(&mutex);
        consumers--;
        if(consumers == 0)
            sem_post(&db);
        sem_post(&mutex);

    }
    pthread_exit(NULL);

我打算让运行ProducerFunc的线程填充整个缓冲区,然后将sem_postaken信号量增加到与占用的槽数相对应的值。然而,在生产者的 sem_post() 上,因等待该信号量而被阻塞的消费者会继续执行,递减信号量并再次循环等待。这解释了为什么生产者在执行 sem_getvalue() 时永远不会看到大于零的值。

如何防止消费者减少信号量,直到生产者执行完其打算执行的所有增量?

最佳答案

等待信号量的全部意义在于,一旦信号量的值大于零,执行此操作的线程就可以立即继续。因此,如果您不希望消费者在生产者发布到您的信号量时立即继续,那么您必须确保消费者当时没有等待该信号量。

我怀疑您正在尝试以信号量不支持的方式使用信号量。信号量的值应解释为传达的唯一信息是信号量在下一次增量之前可以无阻塞地递减的次数。尝试对这些数据进行任何进一步的解释通常是一个坏主意。此外,该数据一返回就必须被视为过时。使用共享变量(通过适当的同步访问)来传达任何其他所需的数据。

话虽如此,您确实有第二个信号量,您将其命名为“互斥体”。您正在使用它做什么的细节看起来很可疑,但如果您确实想阻止消费者在生产者准备好之前继续进行,并且 sem_posTaken 信号量无法充分传达生产者的准备情况,那么显而易见的解决方案是使用单独的信号量来执行此操作 - 也许是互斥体。

关于c - 如何防止一个线程递减信号量,直到另一个线程准备好为止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37841932/

相关文章:

c - 使用 pthread 我的应用程序内存使用量正在增长

c - 特定时间的 sem_timedwait()

semaphore - Cypress:在第一次失败时中断所有测试

c - 查找代码的内存访问冲突

C - 如何拆分用户输入的字符串

c - 指向局部指针数组的全局指针

c - 编译 C 程序时出错

c++ - 为 pthreads 增加 solaris 上子线程的堆栈大小

c - 如何在 void 函数中通过命令行参数传递多个值?

ubuntu - Ubuntu 中的信号量和锁