使用循环缓冲区和生产者/使用者设计模式时是否需要Mutex

时间:2018-09-26 16:39:42

标签: c multithreading mutex

我有两个线程通过循环缓冲区进行通信。

/* Initialize not_full semaphore to a count of BUFFER_SIZE */
sem_init(&not_full_semaphore, 0, BUFFER_SIZE);
/* Initialize not_empty semaphore to a count of 0 */
sem_init(&not_empty_semaphore, 0, 0);

void producer_thread (void) {
    int item
    int head = 0;

    while(true) {
        item = produce_item();

        sem_wait(&not_full_semaphore);
        mutex_lock(&circular_buffer_mutex);
        /* Insert item into the buffer */
        circular_buffer[head] = item;
        /* Increment head offset and wrap if necessary */
        head = (head == BUFFER_SIZE - 1) ? 0 : head + 1;
        mutex_unlock(&circular_buffer_mutex);
        sem_post(&not_empty_semaphore);
    }
}

void consumer_thread (void){
    int item;
    int tail = 0;

    while(true) {
        sem_wait(&not_empty_semaphore);
        mutex_lock(&circular_buffer_mutex);
        /* Remove item from the buffer */
        item = circular_buffer[tail];
        /* Increment tail offset and wrap if necessary */
        tail = (tail == BUFFER_SIZE - 1) ? 0 : tail + 1;
        mutex_unlock(&circular_buffer_mutex);
        sem_post(&not_full_semaphore);
        consume_item(item);
    }

我的问题是我真的需要互斥体吗?在我看来,生产者和消费者不可能同时访问相同的内存。直到生产者完成书写并通过not_empty信号灯发出信号,消费者才会阅读。并且not_full信号量将阻止生产者重新包装并再次写入。因此,我似乎不需要互斥体,但是我发现的所有示例都使用了它。

1 个答案:

答案 0 :(得分:0)

  

我的问题是我真的需要互斥锁吗?

是的。

没有互斥锁,因为您将not_full_semaphore初始化为一个可能大于1的值,所以在此代码中:

while(true) {
    item = produce_item();

    sem_wait(&not_full_semaphore);

    // can reach here while the consumer thread is
    // accessing the circular buffer

    // but this mutex prevents both threads from
    // accessing the circular buffer simultaneously
    mutex_lock(&circular_buffer_mutex);

您的生产者线程在生产下一个项目之前不会等待消费者线程完成。

  

not_full信号量将阻止生产者回绕并再次写。

那是不正确的。如果将not_full_semaphore初始化为大于1的值,则生产者线程不必等待使用者线程。