0

I have multiple threads using "printf". "Printf" is not thread safe. So can I use a mutex around it to make it thread safe? Or are there still concurrency issues?

// member
std::mutex mtxTcp;

// inside a function
      mtxTcp.lock();
      printf("Hello %d\n", u16Id);
      mtxTcp.unlock();
sj95126
  • 6,520
  • 2
  • 15
  • 34
jdl
  • 6,151
  • 19
  • 83
  • 132
  • See https://stackoverflow.com/questions/23586682/how-to-use-printf-in-multiple-threads – kalyanswaroop Oct 07 '21 at 18:09
  • Short answer: Sure - go for it. Longer answer: Q: Do you think the "risk" warrants adding mutexes? Or is it "overkill"? Q: By "thread safe", do you mean "risk of crashing" (the mutexes will help - but the risk is minimal), or do you mean "text could get scrambled amidst concurrent printfs on different threads"? If the latter, be sure to add an [fflush()](https://man7.org/linux/man-pages/man3/fflush.3.html). See also: https://stackoverflow.com/a/40186101/421195 – paulsm4 Oct 07 '21 at 18:09
  • 1
    Side note: Place the locked region inside a block and use [`std::lock_guard`](https://en.cppreference.com/w/cpp/thread/lock_guard) or [`std::scoped_lock`](https://en.cppreference.com/w/cpp/thread/scoped_lock). `printf` isn't going to throw any exceptions or otherwise cause an exit from the regular flow of the code through irregular means that aren't as bad as leaving the mutex locked, but there's nothing worse than someone coming along later and adding a few lines of code that can. eg: `{ const std::lock_guard lock(mtxTcp); printf("Hello %d\n", u16Id); }` – user4581301 Oct 07 '21 at 18:18
  • Also consider making a `thread_safe_printf` function and replace all at-risk calls to `printf` with it. Keeps the code duplication down and you can replace the guts of the function with something better with less impact on the rest of the code. – user4581301 Oct 07 '21 at 18:22
  • 1
    printing can be a bit slow, a good principle is to keep the duration of your locks as short as you can. So you could also queue your print commands and let one other thread handle them. Something along these lines : https://onlinegdb.com/QDx2jaxhM (downside could be you loose synchronization with your programs progress, output can lag behind) – Pepijn Kramer Oct 07 '21 at 20:17
  • Side note: This is C++. You sure you want to use `printf`? – user4581301 Oct 07 '21 at 20:36
  • In C++20, there are std::syncstreams. You could use them if you have c++20. see https://en.cppreference.com/w/cpp/io/basic_osyncstream – Captain Hatteras Oct 08 '21 at 17:56

1 Answers1

1

Yes, but don't use the mutex directly:

{  // added scope
      std::lock_guard lock{mtxTcp};
      printf("Hello %d\n", u16Id);
}
Captain Hatteras
  • 490
  • 3
  • 11
  • 1
    Note that this could potentially lock for a long, long time. It is a good simple solution, but a solution with a message queue and a single thread printing the message queue may be a better choice. With a message queue the mutex will only be locked long enough to add a message to or remove the message from the queue. Both are over in significantly less time than formatting the message and writing it to the output stream. – user4581301 Oct 08 '21 at 00:34