【问题标题】:how to wait effectively on a set of semaphore?如何有效地等待一组信号量?
【发布时间】:2013-03-27 04:22:03
【问题描述】:

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

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

生产者代码:

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 时间。

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

【问题讨论】:

  • 共享资源池应该由一个信号量控制,而不是由一组信号量控制。

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


【解决方案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) { 
        }
    }
}

您可以使用pthread_cond_t 条件变量来表示您的信号量集中的某些内容发生了变化,而不是使用list_changed_semaphore 的信号量。 list_changed_semaphore 不需要像这里的例子那样是一个计数器,它只需要一个位来表示生产者已经修改了列表。

【讨论】:

  • Pillips:感谢您周到的回答!它解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
  • 1970-01-01
  • 2015-06-21
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
相关资源
最近更新 更多