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