Вопрос возникает после прочтения некоторых кодов, написанных другими разработчиками, поэтому я провел небольшое исследование и нашел статью Андрея Александреску. В его статья он говорит, что можно использовать переменную логическую переменную для занятого ожидания (см. первый пример с Wait / Wakeup)
class Gadget
{
public:
void Wait()
{
while (!flag_)
{
Sleep(1000); // sleeps for 1000 milliseconds
}
}
void Wakeup()
{
flag_ = true;
}
...
private:
bool flag_;
};
Я действительно не понимаю, как это работает.
Так почему же так много людей используют изменчивый bool для занятого ожидания и действительно ли он переносим?
В статье не говорится, что volatile
это все, что вам нужно (на самом деле, это не так), только то, что это может быть полезно.
Если вы сделаете это, и если вы используете простой общий компонент
LockingPtr
, Вы можете писать поточно-ориентированный код и гораздо меньше беспокоиться о состоянии гонки, потому что компилятор будет беспокоиться за вас и будет старательно указывать места, где вы ошибаетесь.
Я действительно не понимаю, как это работает.
Он опирается на два предположения:
Первый, вероятно, будет придерживаться любой разумной архитектуры. Второе относится к любой одноядерной архитектуре и к многоядерным архитектурам, широко используемым сегодня, но нет никакой гарантии, что она сохранится в будущем.
приведенный выше код можно безопасно переписать с помощью C ++ 11, используя
std::atomic
Сегодня это может и должно быть. В 2001 году, когда была написана статья, не так уж много.
если у нас более одной записи, у нас могут быть проблемы с упорядочением памяти
В самом деле. Если этот механизм используется для синхронизации с другими данными, то мы полагаемся на третье предположение: этот порядок изменений сохраняется. Опять же, большинство популярных процессоров дают такое поведение, но нет никаких гарантий, что это будет продолжаться.
почему так много людей используют изменчивый bool для занятого ожидания
Потому что они не могут или не будут менять привычки, которые они сформировали до того, как C ++ приобрел модель многопоточной памяти.
и это действительно портативный?
Нет. Модель памяти C ++ 11 не гарантирует ни одно из этих предположений, и есть большая вероятность того, что они станут непрактичными для поддержки будущего оборудования по мере роста типичного числа ядер. volatile
никогда не был решением для синхронизации потоков, и теперь это вдвойне важно, поскольку язык действительно обеспечивает правильные решения.