У меня есть потребительский поток, который должен читать из буфера без блокировки. Хорошо, если операция должна быть пропущена, потому что поток производителя записывает в буфер. Итак, мне кажется, что наиболее подходящим выбором является атомарный TestAndSet на каком-то флаге.
Теперь эти вышеупомянутые потоки производителей должны также соблюдать этот флаг, потому что они не могут начать запись в буфер, пока потребитель читает из него. Я мог бы решить эту проблему, используя atomic_flag :: test_and_set, как в следующем коде:
while (flag.test_and_set())
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
…но написание собственной спин-блокировки кажется не идеальным. Я бы предпочел, чтобы моя нить спала, пока она не проснулась в результате очистки флага. Что-то вроде:
flag.enter();
TLDR: Как лучше всего синхронизировать два потока, где один может заблокировать, а другой нет?
Использовать std::mutex
,
Читатели могут использовать try_lock
чтобы избежать блокировки.
Авторы (продюсеры) могут использовать блокировку lock
функционировать как обычно.
Конечно, чтобы избежать утечки замка, используйте std::unique_lock
. Читатели должны пройти std::try_to_lock
как второй аргумент. Затем вы должны проверить owns_lock()
чтобы увидеть, можно ли безопасно прочитать данные или в процессе записи.
Вы не можете смешивать и сочетать методы синхронизации — обе стороны должны согласиться. Мне кажется, что вы действительно хотите попытаться получить блокировку, а затем, если она не работает, пропустить. Ты можешь использовать try_lock на регулярной std::mutex
для достижения этой цели.
Без блокировки невозможно, если вы хотите, чтобы производитель блокировал, когда читатель читает.