Смешивание синхронизации без блокировки и с полной блокировкой потока с атомарным 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 для достижения этой цели.

Без блокировки невозможно, если вы хотите, чтобы производитель блокировал, когда читатель читает.

Другие вопросы по тегам