From: Tor L. <tm...@ik...> - 2009-12-16 19:45:27
|
But to get back to the original poster's question, as far as I can see there isn't any rand_r() "in MinGW" . I don't know what he meant exactly by thread-safe, though... That each thread has a separate state and separately seedable sequence of random numbers (and thus threads that use the same seed, perhaps the implicit one if no srand() is called, get the same sequence)? Or that they share state (in a thread-safe manner, protected by lock if not atomically updated) and thus even if srand() is not called the sequence is different in each thread? Either of the above interpretation can justifiablty be said to be "thread-safe" imho. Or something slightly different? Anyway, the srand() and rand() functions in msvcrt.dll (which is the C library that MinGW-built code uses) seem to use per-thread state that is separately seeded, i.e. any srand() call in the "main" thread before another thread is started doesn't affect the seed used in the thread. Try the following test program: #include <stdio.h> #include <stdlib.h> #include <math.h> #include <process.h> #define _WIN32_WINNT 0x0500 #include <windows.h> static unsigned __stdcall doit (void *data) { int i; volatile int k; int *ip = data; /* Let each thread run for a significant time so that we are more * likely to get overlapped execution. */ for (i = 0; i < 100000000; i++) k = rand (); for (i = 0; i < ip[0]; i++) ip[i+1] = rand (); return 0; } int main (int argc, char **argv) { int *ia0, **ia; HANDLE *handles; int i, j; int seed; int nnums; int nthreads; if (argc != 4) { fprintf (stderr, "Usage: %s seed nnums nhreads\n" " seed is the srand() seed to use in main(), use zero for no explicit seed\n" " nnums is the number of rand() calls\n" " nthreads is the number of threads to use\n", argv[0]); exit (1); } seed = atoi (argv[1]); nnums = atoi (argv[2]); nthreads = atoi (argv[3]); ia0 = malloc ((nnums + 1) * sizeof(int)); ia0[0] = nnums; if (seed != 0) srand (seed); doit (ia0); ia = malloc (nthreads * sizeof (int *)); handles = malloc (nthreads * sizeof (HANDLE)); /* Start n threads */ for (j = 0; j < nthreads; j++) { unsigned tid; ia[j] = malloc ((nnums + 1) * sizeof (int)); ia[j][0] = nnums; _beginthreadex (NULL, 0, doit, ia[j], 0, &tid); handles[j] = OpenThread (SYNCHRONIZE, FALSE, tid); } printf ("In main thread:\n"); for (i = 0; i < nnums; i++) printf ("%8d\n", ia0[i+1]); /* Wait for the threads to finish */ for (j = 0; j < nthreads; j++) WaitForSingleObject (handles[j], INFINITE); for (j = 0; j < nthreads; j++) { printf ("Thread %d:\n", j); for (i = 0; i < nnums; i++) printf ("%8d\n", ia[j][i+1]); } return 0; } |