Важно различать атомарный доступ (который гарантирует, что чтение / изменение / запись значения выполняется как одна атомная единица) и переупорядочение памяти.
Барьеры памяти предотвращают переупорядочение операций чтения и записи, и переупорядочение полностью ортогонально атомарности. Например, в PowerPC, если вы реализуете наиболее эффективный атомарный инкремент, то это не помешает переупорядочению. Если вы хотите предотвратить переупорядочение, вам нужна инструкция lwsync или sync или какой-либо эквивалентный высокоуровневый (C ++ 11?) Барьер памяти.
Утверждения о том, что «нет никакой возможности перекомпоновать компилятор проблемным способом», кажутся наивными общими утверждениями, потому что оптимизация компилятора может быть довольно неожиданной и потому что процессоры (в частности, PowerPC / ARM / Alpha / MIPS) агрессивно переупорядочивают операции с памятью .
Связанный кеш тоже вас не спасет. См. http://preshing.com/, чтобы увидеть, как на самом деле работает переупорядочение памяти.
Однако в этом случае я считаю, что ответ заключается в том, что никаких барьеров не требуется. Это связано с тем, что для этого конкретного случая (подсчета ссылок) нет необходимости в связи между количеством ссылок и другими значениями в объекте. Единственное исключение - когда счетчик ссылок достигает нуля. На этом этапе важно убедиться, что все обновления из других потоков видны текущему потоку, поэтому может потребоваться барьер для чтения-чтения .