Мой первый ответ касался вашего примера инициализации синглтона, но, как вы подчеркнули при редактировании своего вопроса, вы переходите к более общим ошибкам C ++, когда мы переходим к многоядерным и многопоточным приложениям. Следующее является настоящим сюрпризом, когда вы впервые сталкиваетесь с этим. Хотя он не специфичен для C ++, он определенно влияет на код C ++.
Прекращение выполнения и барьеры памяти (или ограждения):
Одна ошибка не выполнена. Потоки могут видеть операции других потоков, выполняющихся на разных ядрах не по порядку, благодаря современному оборудованию, позволяющему оптимизировать исполнение по порядку. В результате многопоточный код, который работает правильно на одноядерном компьютере, может фактически быть неправильным на многоядерном компьютере.
Наивным решением таких проблем является расширение области применения критических секций. Другой способ - использовать барьеры памяти или алгоритмы без блокировки.