1. A method of detecting a datarace between first and second memory accesses within a program, comprising: determining whether the first and second memory accesses are to the same memory location; determining whether the first and second memory accesses are executed by different threads in the program; determining whether the first and second memory accesses are guarded by a common synchronization object; and determining whether there is an execution ordering enforced between the first and second memory accesses.