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; determining whether there is an execution ordering enforced between the first and second memory accesses; and determining that a datarace exists between the first and second memory accesses if the first and second memory accesses are both to the same memory location, the first and second memory accesses are executed by different threads in the program, the first and second memory accesses are not guarded by a common synchronization object, and there is no execution ordering enforced between the first and second memory accesses, wherein said determining whether there is an execution ordering enforced between the first and second memory accesses comprises: introducing a thread/ordering synchronization object for each thread in the program; and performing a thread/ordering mon-enter operation on the thread/ordering synchronization object at the start of the thread, and performing a thread/ordering mon-exit operation on the thread/ordering synchronization object at the termination of the thread, thereby using mutual exclusion to model executions orderings enforced by thread join operations.