An insidious race condition arises in the following situation (which I encountered in Objective-C, but any language that passes by reference will allow for the same):
I have a consumer function which writes a message to a file or database and which can be called by multiple threads - so it is LOCKed. This function is called by threads generated by a loop, where the thread instantiation function takes as parameter a string which is modified by each loop iteration. E.g., in pseudo-C:
string msg;
for( i = 0; i < 10; i++ ){
fsprintf( msg, "parameter: %i", i );
launchThread( msg );
}
void launchThread( string parm ){
plock lock;
fprintf( fHandle, parm );
plock unlock;
}
Of course since the fprintf needs to be atomic (in order not to generate a bus error), it is the one that has to be locked. However, msg is a shared resource as well. If you run this code as it is you will get an output similar to the following:
parameter20
parameter20
parameter30
Instead of the expected:
parameter1
parameter2
parameter3
That is because msg is modified by the loop and by the time thread #x has picked it up, who knows what value it has - certainly not one in sync with #x.
The solution is to provide as parameter to the thread a full immutable copy of msg and not a reference to msg.