Volatile не бесполезен для совместного доступа несколькими потоками, просто этого не обязательно достаточно:
- это не обязательно обеспечивает семантику барьера памяти, которая может потребоваться;
- он не обеспечивает гарантий атомарного доступа (например, если размер летучего объекта больше, чем размер слова в памяти собственной платформы)
Кроме того, вы также должны заметить, что спецификатор volatile
в аргументах указателя на API в вашем примере действительно только дает API возможность получать указатели на volatile
объекты без жалоб - это не требует что указатели указывают на фактические volatile
объекты. Стандарт позволяет автоматически преобразовывать неквалифицированный указатель в квалифицированный указатель. Автоматический переход в другую сторону (квалифицированный указатель на неквалифицированный) в стандарте не предусмотрен (компиляторы обычно допускают это, но выдают предупреждение).
Например, если InterlockedIncrement()
был создан как:
LONG __cdecl InterlockedIncrement(__inout LONG *Addend); // not `volatile*`
API все еще может быть реализован для правильной внутренней работы. Однако, если у пользователя был непостоянный объект, который он хотел бы передать API, приведение было бы необходимо, чтобы компилятор не выдавал предупреждение.
Поскольку (необходимо или нет), эти API часто используются с volatile
квалифицированными объектами, добавление квалификатора volatile
в аргумент указателя предотвращает создание бесполезной диагностики при использовании API и ничего не вредит, когда API используется с указателем на энергонезависимый объект.