There are a number of atomic operations defined in include/asm/atomic.h: these are guaranteed to be seen atomically from all CPUs in the system, thus avoiding races. If your shared data consists of a single counter, say, these operations might be simpler than using spinlocks (although for anything non-trivial using spinlocks is clearer).
Note that the atomic operations are defined to act as both read and write barriers on all platforms.