В качестве примера того, как все может пойти не так:
Достаточно умный компилятор может увидеть, что mutex.lock()
не может изменить возвращаемое значение list.empty()
и, таким образом, полностью пропустить внутреннюю проверку if
, в конце концовприводя к pop_back
в списке, последний элемент которого был удален после первого if
.
Почему он может это сделать? Синхронизация в list.empty()
отсутствует, поэтому, если бы она была изменена одновременно, это привело бы к гонке данных. Стандарт гласит, что программы не должны иметь гонки данных, поэтому компилятор примет это как должное (в противном случае он может почти не выполнять оптимизацию). Следовательно, он может предполагать однопоточную перспективу несинхронизированного list.empty()
и делать вывод, что он должен оставаться постоянным.
Это только одна из нескольких оптимизаций (или поведения оборудования), которые могут нарушить ваш код.