Intel® C++ Compiler 16.0 User and Reference Guide
Even if you properly use a lock to protect a resource (such as a simple variable or a list or other data structure), the actual order that two strands modify the resource is not deterministic. For example, suppose the following code fragment is part of a function that is spawned, so that several strands may be executing the code in parallel.
. . . // Update is a function that modifies a global variable, gv. sm.lock(); Update(gv); sm.unlock(); . . .
Multiple strands will race to acquire the lock, sm, so the order in which gv is updated will vary from one program execution to the next, even with identical program input. This is the source of non-determinism, but it is not a data race as defined in Data Races.
This non-determinacy may not cause a different final result if the update is a commutative operation, such as integer addition. However, many common operations, such as appending an element to the end of a list, are not commutative, and so the result varies based on the order in which the lock is acquired.