многопоточность — смешивание синхронизации без блокировки и с полной блокировкой потока с атомарным TestAndSet в переполнении стека

У меня есть потребительский поток, который должен читать из буфера без блокировки. Хорошо, если операция должна быть пропущена, потому что поток производителя записывает в буфер. Итак, мне кажется, что наиболее подходящим выбором является атомарный TestAndSet на каком-то флаге.

Теперь эти вышеупомянутые потоки производителей должны также соблюдать этот флаг, потому что они не могут начать запись в буфер, пока потребитель читает из него. Я мог бы решить эту проблему, используя atomic_flag :: test_and_set, как в следующем коде:

while (flag.test_and_set())
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}

…но написание собственной спин-блокировки кажется не идеальным. Я бы предпочел, чтобы моя нить спала, пока она не проснулась в результате очистки флага. Что-то вроде:

flag.enter();

TLDR: Как лучше всего синхронизировать два потока, где один может заблокировать, а другой нет?

1

Решение

Использовать std::mutex,

Читатели могут использовать try_lock чтобы избежать блокировки.

Авторы (продюсеры) могут использовать блокировку lock функционировать как обычно.

Конечно, чтобы избежать утечки замка, используйте std::unique_lock. Читатели должны пройти std::try_to_lock как второй аргумент. Затем вы должны проверить owns_lock() чтобы увидеть, можно ли безопасно прочитать данные или в процессе записи.

4

Другие решения

Вы не можете смешивать и сочетать методы синхронизации — обе стороны должны согласиться. Мне кажется, что вы действительно хотите попытаться получить блокировку, а затем, если она не работает, пропустить. Ты можешь использовать try_lock на регулярной std::mutex для достижения этой цели.

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

1

По вопросам рекламы [email protected]