Forivin
Forivin

Reputation: 15538

C++ Printing/cout overlaps in multithreading?

I was wondering how I could handle printing when using multiple threads.
I thought it would be pretty simple:

#include <iostream>
#include <pthread.h>
using namespace std;

bool printing = false;

struct argumentStruct {
    int a;
    float b;
};

void *ThreadFunction(void *arguments) {
  struct argumentStruct*args = (struct argumentStruct*)arguments;
  int a = args->a;
  float b = args->b;
    while (printing) {}
    printing = true;
      cout << "Some text...." << a << b << endl;
    printing = false;
}

main() {
    pthread_t threads[3];
    struct argumentStruct argStruct[3];

    argStruct[0].a = 1;
    argStruct[0].b = 1.1;
    pthread_create(&threads[0], NULL, &ThreadFunction, (void *)&argStruct[0]);

    argStruct[1].a = 2;
    argStruct[1].b = 2.2;
    pthread_create(&threads[1], NULL, &ThreadFunction, (void *)&argStruct[1]);

    argStruct[2]a = 3;
    argStruct[2].b = 3.3;
    pthread_create(&threads[2], NULL, &ThreadFunction, (void *)&argStruct[2]);

    getchar();
    return 0;
}

But this doesn't really work that well. Some couts are just skipped (or maybe overwritten?).
So what am I doing wrong? How can I handle this properly?

Upvotes: 0

Views: 1999

Answers (2)

Claudi
Claudi

Reputation: 5416

The problem is that the statements that test and set the printing variable are not atomic, i.e., they don't execute without being interrupted by the OS scheduler which switches the CPU among threads. You should use mutexes in order to stop other threads while printing. Here you have a nice example:

http://sourcecookbook.com/en/recipes/70/basic-and-easy-pthread-mutex-lock-example-c-thread-synchronization

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409442

You have a race condition, where two (or more) threads can both set printing to true.

This is because assignment is not an atomic operation, it's done in multiple steps by the CPU, and if the thread is interrupted before the actual setting of the variable to true, and another thread starts running, then you can have two threads running simultaneously both believing the variable is true. For more clarity:

  1. Thread A sees that printing is false
  2. Thread A is interrupted
  3. Thread B starts running
  4. Thread B sees that printing is false
  5. Thread B sets printing to true
  6. Thread B is interrupted
  7. Thread A is scheduled and starts running again
  8. Thread A sets printing to true

Now both thread A and B are running full speed ahead.

That's why there are threading primitives such as semaphores and mutex that handle these things.

Upvotes: 1

Related Questions