Нужен ли мне Mutex при использовании кругового буфера и шаблона проектирования «производитель / потребитель» - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть два потока, которые общаются через кольцевой буфер.

/* 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 голосов
/ 26 сентября 2018

Мой вопрос: действительно ли мне нужен мьютекс?

Да, вы делаете.

Без мьютекса, поскольку вы инициализируете свой not_full_semaphore значениемэто потенциально больше единицы в этом коде:

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 инициализируется значением больше единицы.

...