2013-11-12 5 views
1

Вопрос возникает после прочтения некоторых кодов, написанных другими разработчиками, поэтому я провел некоторое исследование, и я нашел статью Андрея Александреску. В своем article он говорит, что можно использовать энергонезависимую логическую переменную для активного ожидания (см первый пример с Wait/Wakeup)еще одна тема о volatile

class Gadget 
{ 
public: 
    void Wait() 
    { 
     while (!flag_) 
     { 
      Sleep(1000); // sleeps for 1000 milliseconds 
     } 
    } 
    void Wakeup() 
    { 
     flag_ = true; 
    } 
    ... 
private: 
    bool flag_; 
}; 

Я не очень понимаю, как это работает.

  1. volatile не гарантирует, что операции будут атомарными. Практически чтение/запись в логическую переменную являются атомарными, но теория не гарантирует этого. С моей точки зрения, приведенный выше код можно было бы безопасно переписать с помощью C++ 11, используя функции std :: atomic :: load/store с ограничениями порядка хранения/освобождения памяти соответственно.
  2. У нас нет этой проблемы в описанном примере, но если у нас есть более одной записи, у нас могут быть проблемы с упорядочением памяти. Volatile - это не забор, он не форсирует порядок памяти, а просто предотвращает оптимизацию компилятора.

Так почему же так много людей используют volatile bool для оживленного ожидания и действительно ли он переносится?

+0

Я не авторитет в этой области, но мой инстинкт такой же, как ваш. Также может быть стоит отметить, что в вашем коде нет 'volatile bool';) Также возможно, что статья относится к 1 февраля 2001 года. –

+1

[Возможный ответ] (http://stackoverflow.com/a/4168894/560648) по почти дублированному вопросу. –

+0

Да, вы правы. Я скопировал исходный код из первого примера, он добавляет изменчивость позже. Позвольте мне это исправить. – axe

ответ

2

В статье не говорится, что volatile - это все, что вам нужно (действительно, это не так), только то, что это может быть полезно.

Если вы сделаете это, и если вы используете простой общий компонент LockingPtr, вы можете написать поточно-код и беспокоиться меньше об условиях гонки, потому что компилятор будет переживать за вас и будет старательно указывают где вы ошибаетесь.

+0

Если это так, то ясно, однако я говорил об этой части «Большинство объяснений обоснования и использования неустойчивой остановки здесь и советуют вам волатильно-квалифицировать примитивные типы, которые вы используете в нескольких потоках. Тем не менее, есть намного больше, что вы можете сделать с изменчивым, потому что это часть замечательной системы типа C++. «Он не говорит, что люди, которые советуют использовать volatile для примитивных типов, используемых в нескольких потоках, ошибочны, потому что на самом деле волатильность не имеет ничего для многопоточности в C++. – axe

+0

@axe: Ну, а как насчет этого? 'volatile' _is_ части системы типов, поэтому вы можете выбрать перегрузки на ее основе. Вы должны рассматривать его как _one tool_ среди многих в возможной конструкции многопоточного приложения. –

+0

Откуда вы его взяли? :) – axe

0

Я действительно не понимаю, как это работает.

Он основан на двух предположениях:

  • читает и записывает логические переменные являются неделимыми;
  • все потоки имеют единый вид памяти, так что изменения, сделанные в одном потоке, будут видны другим в течение короткого промежутка времени без явного ограничения памяти.

Первый, вероятно, будет содержать любую разумную архитектуру. Второе относится к любой одноядерной архитектуре и к многоядерным архитектурам, широко используемым сегодня, но нет никакой гарантии, что она будет продолжаться и в будущем.

код выше, можно смело переписать с C++ 11 с помощью std::atomic

Сегодня, оно может и должно быть. В 2001 году, когда статья была написана, не так много.

, если у нас есть более одной записи, мы можем иметь проблемы с памятью заказа

Действительно.Если этот механизм используется для синхронизации с другими данными, то мы полагаемся на третье предположение: этот порядок модификации сохраняется. Опять же, большинство популярных процессоров дают такое поведение, но нет никакой гарантии, что это будет продолжаться.

почему так много людей используют летучее BOOL для занятого ожидания

Потому что они не могут или не менять привычки они сформировались до C++ приобрел многопоточную модель памяти.

и действительно ли он переносится?

№. Модель памяти C++ 11 не гарантирует ни одно из этих допущений, и есть хорошие шансы, что они станут непрактичными для будущего оборудования, которое будет поддерживаться, по мере роста типичного количества ядер. volatile никогда не был решением для синхронизации потоков, и теперь это вдвойне говорит о том, что язык предоставляет правильные решения.

Смежные вопросы