Yes you need both compiler barriers for the ordering, as well as memory fences to ensure the global visibility of previous operations in order.
It is possible that the mutex implementation he used does no spinning in case of contention and just context switches each time. That could explain the poor performance of mutexes but I don't know the implementation.