如何有效地等待一组信号量?

时间:2013-03-27 04:22:03

标签: c++ shared-memory semaphore busy-waiting

我正在使用具有共享内存的信号量来进行多生产者和多客户端之间的通信。我的系统中有两种主要的信号量,即“存储的信号量”和“已处理的信号量”。

系统运行如下:生产者不断地将数据放入共享内存,然后增加存储的信号量值,而消费者在循环中,等待这样存储的信号量。消费者在收到生产者的数据后,将处理这些数据,然后增加处理后的信号量值。制作人将通过等待“已处理的信号量”获得结果

生产者代码:

for(int i =0;i<nloop;i++){
    usleep(100);
    strcpy(shared_mem[i], "data for processing");
    sem_post(&shared_mem[i].stored_semaphored);
    if(sem_timedwait(&msg_ptr->processed_semaphore,&ts)==-1){ //waiting for result 
        if(errno == ETIMEDOUT){
        }
        break;
    }else{
       //success
    }

}

消费者代码:

for (int j = 0; j < MAX_MESSAGE; j++) {
if (sem_trywait(&(shm_ptr->messages[j].stored_semaphore)) == -1) { 
    if (errno == EAGAIN) {
    } else {
            //success ==> process data
            //post result back on the shared memory, and increase                         
            //the processed semahore
        strcpy(shared_mem[j].output, "Processed data");
        sem_post(&(shared_mem[j].processed_semaphore)); 
    }
}
}//for loop over MAX_MESSAGE

我的问题是消费者代码中的for循环浪费了几乎100%的CPU,因为在没有来自生产者的数据的情况下,这个for循环连续运行。

我的问题是还有其他方法可以等待一组信号量(可能类似于SELECT,POLL或EPOLL的等待机制),这不会浪费CPU时间。

希望看到你的答案。非常感谢!

1 个答案:

答案 0 :(得分:1)

据我所知,没有办法等待一组信号量。这意味着所有访问都需要通过单个信号量进行汇集。你循环遍历一组信号量,因此它们可以共同成为一个对象。消费者需要知道任何信号量何时发出信号,因此在新信号量上使用额外的sem_post来表示该信号量集已经发生变化。

你的制作人代码变成这样:

....
sem_post(&shared_mem[i].stored_semaphored);
sem_post(&list_changed_semaphore); /* Wake the consumer. */
....

和消费者:

/* Block until a consumer has indicated that it has changed the semaphore list */
if (!sem_wait(&list_changed_semaphore)) {
    /* At least one producer has signalled a change. */
    for (int j = 0; j < MAX_MESSAGE; j++) {
        if (sem_trywait(&(shm_ptr->messages[j].stored_semaphore)) == -1) { 
        }
    }
}

您可以使用list_changed_semaphore条件变量来表示您的信号量集中的某些内容已更改,而不是使用pthread_cond_t的信号量。 list_changed_semaphore不需要是一个计数器,如此处所示的示例,它只需要一个位来指示生产者已经修改了列表。