В этом случае (в зависимости от реализации .reset
и !
) может возникнуть проблема, когда поток 1 проходит неполный путь при инициализации resource_ptr
, а затем останавливается / переключается. Затем появляется поток 2, выполняет первую проверку, видит, что указатель не равен нулю, и пропускает проверку блокировки / полностью инициализированной проверки. Затем он использует частично инициализированный объект (вероятно, в результате чего происходят плохие вещи). Затем поток 1 возвращается и завершает инициализацию, но уже слишком поздно.
Причина, по которой возможна частично инициализированная resource_ptr
, заключается в том, что ЦПУ разрешено переупорядочивать инструкции (при условии, что он не изменяет однопоточное поведение). Таким образом, хотя код выглядит так, как будто он должен полностью инициализировать объект и затем присвоить его resource_ptr
, оптимизированный код сборки может делать что-то совсем другое, и ЦПУ также не гарантированно будет выполнять инструкции по сборке в порядке, в котором они указаны в двоичном виде!
Вывод состоит в том, что когда задействованы несколько потоков, ограждения памяти (блокировки) являются единственным способом гарантировать, что все происходит в правильном порядке.