【问题标题】:Making printf thread safe?使 printf 线程安全?
【发布时间】:2021-10-07 18:07:32
【问题描述】:

我有多个使用“printf”的线程。 “Printf”不是线程安全的。 那么我可以在它周围使用互斥锁来使其线程安全吗? 还是还有并发问题?

// member
std::mutex mtxTcp;

// inside a function
      mtxTcp.lock();
      printf("Hello %d\n", u16Id);
      mtxTcp.unlock();

【问题讨论】:

  • 简短回答:当然 - 去吧。更长的答案: 问:您认为“风险”是否值得添加互斥锁?还是“矫枉过正”?问:“线程安全”是指“崩溃的风险”(互斥锁会有所帮助 - 但风险很小),还是“文本可能在不同线程上的并发 printfs 中被打乱”?如果是后者,请务必添加fflush()。另见:stackoverflow.com/a/40186101/421195
  • 旁注:将锁定区域放在块内并使用std::lock_guardstd::scoped_lockprintf 不会抛出任何异常或以其他方式导致通过不规则方式退出常规代码流,这并不像让互斥锁锁定那么糟糕,但没有什么比后来有人来添加一个更糟糕的了几行代码就可以了。例如:{ const std::lock_guard<std::mutex> lock(mtxTcp); printf("Hello %d\n", u16Id); }
  • 还可以考虑创建一个thread_safe_printf 函数并用它替换所有对printf 的风险调用。减少代码重复,您可以用对其余代码影响较小的更好的东西替换函数的核心。
  • 打印可能会有点慢,一个好的原则是尽可能缩短锁定的持续时间。因此,您还可以将打印命令排队并让另一个线程处理它们。这些方面的东西:onlinegdb.com/QDx2jaxhM(缺点可能是您与程序进度的同步松散,输出可能会滞后)

标签: c++


【解决方案1】:

可以,但不要直接使用互斥锁:

{  // added scope
      std::lock_guard lock{mtxTcp};
      printf("Hello %d\n", u16Id);
}

【讨论】:

  • 请注意,这可能会锁定很长时间。这是一个很好的简单解决方案,但具有消息队列和单线程打印消息队列的解决方案可能是更好的选择。使用消息队列,互斥锁将仅被锁定足够长的时间以将消息添加到队列或从队列中删除消息。与格式化消息并将其写入输出流相比,两者的结束时间都要短得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 2011-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多