Должны ли переменные состояния по-прежнему нуждаться в мьютексе, если вы меняете проверяемое значение атомарно?

Вот типичный способ использования переменной условия:

// The reader(s)
lock(some_mutex);
if(protected_by_mutex_var != desired_value)
    some_condition.wait(some_mutex);
unlock(some_mutex);

// The writer
lock(some_mutex);
protected_by_mutex_var = desired_value;
unlock(some_mutex);
some_condition.notify_all();

Но если protected_by_mutex_var устанавливается атомарно, скажем, команда сравнения и замены, выполняет ли мьютекс какую-либо цель (кроме того, что pthreads и другие API-интерфейсы требуют, чтобы вы передавали мьютекс)? Защищает ли это состояние, используемое для выполнения условия? Если нет, то безопасно ли это сделать?:

// The writer
atomic_set(protected_by_mutex_var, desired_value);
some_condition.notify_all();

С писателем никогда не взаимодействует напрямую с мьютексом читателя? Обратите внимание, что имя "protected_by_mutex_var" больше не подходит (он больше не защищен мьютексом). Если да, то даже необходимо, чтобы разные читатели использовали один и тот же мьютекс?

Ответы

Ответ 1

Представьте себе следующий сценарий:

| Thread 1                                            | Thread 2                                           |
| if(protected_by_mutex_var != desired_value) -> true |                                                    |
|                                                     | atomic_set(protected_by_mutex_var, desired_value); |
|                                                     | some_condition.notify_all();                       |
| some_condition.wait(some_mutex);                    |                                                    |

В этой ситуации поток Thread 1 ожидает уведомления, которое никогда не появится. Поскольку утверждения, действующие на условие, не являются частью переменной read/atomic set, это представляет собой условие гонки.

Использование мьютекса эффективно делает эти действия неотделимыми (при условии, что все обращения к переменной ведут себя правильно и блокируют мьютекс.)