Question

Is the PrintHello() function pthreads example thread-safe? I find these kind of examples online but I don't understand how they can be thread-safe. On the other hand, if I add a mutex around the code in PrintHello() function then the example would not be multithreaded as all threads would queue in wait for the previous thread to exit the PrintHello() function. Also, moving it to a class would not help as the member would have to be statically declared as pointers to non-static functions is not allowed with CreateThread() it seems. Any way of solving this?

#include <WinBase.h>
#include <stdio.h>
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */

#define NUM_THREADS     500

DWORD PrintHello(LPVOID oHdlRequest)
{
   long tid;
   tid = (long)GetCurrentThreadId();

   /* randomly sleep between 1 and 10 seconds */
   int sleepTime = rand() % 10 + 1;   
   sleep(sleepTime);

   printf("Hello World! It's me, thread #%ld!\n", tid);
   return 0;
}

int main (int argc, char *argv[])
{
   /* initialize random seed: */
   srand (time(NULL));

   HANDLE threads[NUM_THREADS];
   long t;
   DWORD nThreadID;

   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);

      threads[t] = CreateThread(
            // Default security
            NULL, 
            // Default stack size
            0, 
            // Function to execute
            (LPTHREAD_START_ROUTINE)&PrintHello,
            // Thread argument
            NULL,
            // Start the new thread immediately
            0, 
            // Thread Id
            &nThreadID
        );    

      if (!threads[t]){
         printf("ERROR; return code from CreateThread() is %d\n", GetLastError());
         exit(-1);
      }
   }
}
Was it helpful?

Solution

Since you're including WinBase.h, I'll assume that you're using MSVC. MSVC CRT has long supported multithreaded access - in fact, current versions of MSVC no longer support a single threaded CRT that isn't threadsafe. I believe that VS 2003 is the last version of MSVC that supported the single threaded CRT.

In the multithreaded CRT, functions are threadsafe and if they access global data internally they will synchronize among themselves. So each printf() executed in ProcessRequest() will be atomic with respect to other printf() calls in other threads (actually, the locks are based on streams, so the printf() calls will be atomic with respect to other CRT functions that use stdout).

The exceptions to this are if you use I/O functions that are explicitly documented to not take locks (so you can synchronize on them yourself for performance reasons), or if you define _CRT_DISABLE_PERFCRIT_LOCKS in which case the CRT assumes that all I/O will be performed on a single thread.

See http://msdn.microsoft.com/en-us/library/ms235505.aspx

POSIX makes similar guarantees that printf() will be threadsafe:

OTHER TIPS

The code is not thread-safe in general; printf is not normally reentrant. (An implementation could add reentrace to it as an additional feature, but I don't know of any which do.) You must add some sort of protection around it. (Under Windows, a so called CriticalSection should be sufficient.)

You'll also have to find a thread safe alternative to sleep; I can't find any documentation which says that it is reentrant (and the Posix variant isn't), but Microsoft doesn't seem to document reentrance in general. A classical solution for this would be to create a Mutex, block it, and then call WaitForSingleObject on it with the desired timeout; CreateWaitableTimer and WaitForSingleObject should work as well. (As I said, Microsoft's documentation is very deficient; but WaitForSingleObject must be safe, since it is des igned to be used when waiting for a mutex, among other things.)

Note too that unless you join the created threads, you'll probably run off the end of main, and the process will terminate before any of the threads will have run. (Under Windows, you can use WaitForSingleObject or WaitForMultipleObjects to join.)

An even better solution would be to the standard threads, if you have a compiler which supports them, or Boost threds, if you don't.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top