0

I've worked a decent amount with threading in C on linux and now I'm trying to do the same but with c++ on Windows, but I'm having trouble with printing to the standard output. In the function the thread carries out I have:

void print_number(void* x){
    int num = *(static_cast<int*> (x));
    std::cout << "The number is " << num << std::endl;
}

wrapped in a loop that creates three threads. The problem is that although everything gets printed, the threads seem to interrupt each other between each of the "<<"'s.

For example, the last time I ran it I got

The number is The number is 2The number is 3
1

When I was hoping for each on a separate line. I'm guessing that each thread is able to write to the standard output after another has written a single section between "<<"s. In C, this wasn't a problem because the buffer wasn't flushed until everything I needed the write was there, but that's not the case now I don't think. Is this a case of a need for a mutex?

Foundry
  • 33
  • 7
  • See this difference between mutex and semaphore http://stackoverflow.com/questions/62814/difference-between-binary-semaphore-and-mutex – Richard Chambers Dec 11 '14 at 04:00

2 Answers2

2

In C++, we first of all would prefer to take arguments as int*. And then, we can just lock. In C++11:

std::mutex mtx; // somewhere, in case you have other print functions 
                // that you want to control

void print_number(int* num) {
    std::unique_lock<std::mutex> lk{mtx}; // RAII. Unlocks when lk goes out of scope
    std::cout << "The number is " << *num << std::endl;
}

If not C++11, there's boost::mutex and boost::mutex::scoped_lock that work the same way and do the same thing.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • Note that, on some platforms (eg Windows) writing to the console is quite expensive (IIRC at least 50ms per call, so 150ms for the single `cout` in the function given here). Locking for the duration of the write often means that you have essentially sequentialised the 'parallel' functions. In these cases, you may well be better off moving the console writes off to a separate thread and using a thread-safe message-passing scheme to pass strings to the writing thread. – Tom Dec 11 '14 at 04:28
1

Your C example worked by accident; printf and the like aren't atomic either.

This is indeed a case for a mutex. I typically allocate it static function locally. E.g.:

void atomic_print(/*args*/) {
    static MyMutex mutex;
    mutex.acquire();
    printf(/*with the args*/);
    mutex.release();
}
Community
  • 1
  • 1
geometrian
  • 14,775
  • 10
  • 56
  • 132
  • @RaphaelM. indeed; this is because `printf` is _threadsafe_ according to the standard, but not (necessarily) _atomic_. See the second link in my answer. – geometrian Dec 11 '14 at 04:23