c++ - 我怎样才能使公共(public)共享对象的访问线程安全?

标签 c++ multithreading synchronization race-condition critical-section

我搜索了整个 SO 论坛,但找不到任何合理的答案。我知道可以通过使用互斥锁和信号量等同步机制使资源共享成为线程安全的,但我的问题是不同的。假设您有一个 Logger 记录器 对象。它通过引用传递给所有正在运行的线程。此 logger 对象有一个 Logger::log 函数,其中资源(日志文件)由多个线程访问。我可以使用该方法用互斥量包装这个关键部分,以防止竞争条件。但是,如何防止多个线程访问共享的 Logger logger 对象时可能发生的竞争条件。我可以将一个通用互斥锁与 Logger logger 对象一起传递,并尝试在使用它之前获取该对象,但该解决方案并不优雅。在这个给定的场景中防止竞争条件的最好方法是什么?

最佳答案

更多与Single Responsibility Principle同步和 not to pay for what you dont use 的 C++ 思想是让 Logger 类只负责日志记录。想象一下,您想重用它来登录单线程应用程序 - 那么为什么要支付额外的同步费用。

当然,对于多线程应用程序——您将需要线程之间的同步机制。实现此目的的一种好方法是使用 Decorator Design Pattern - 如下所示:

class ILogger 
{
public: 
   virtual ~ILogger() = default;

   // as many log methods as you need
   virtual void log(args) = 0;
};

然后让您的 Logger 派生自并实现 ILogger

然后定义为其添加同步的装饰器:

class SynchronizedLogger : public ILogger 
{
public: 
   SynchronizedLogger (ILogger& logger) : logger(logger) {} 

   // as many log methods as you need
   void log(args) override
   {
       std::lock_guard<std::mutex> lock(logGuard);
       logger.log(args);
   }

private:
   std::mutex logGuard;
   ILogger& logger; 
};

您只需确保所有将使用日志记录的线程在 SynchronizedLogger 构造之后启动并在其销毁之前停止:

int main() {
   Logger logger{...}; 
   SynchronizedLogger syncLogger{logger};

   std::thread t1([&syncLogger] { syncLogger.log("T1"); });
   std::thread t2([&syncLogger] { syncLogger.log("T2"); });
   std::thread t3([&syncLogger] { syncLogger.log("T3"); });
   std::thread t4([&syncLogger] { syncLogger.log("T4"); });

  t1.join();
  t2.join();
  t3.join();
  t4.join();
}

关于c++ - 我怎样才能使公共(public)共享对象的访问线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49640384/

相关文章:

c++ - C++ 中的 main() 是否重载?

python - 如何为可以发送和接收消息的mqtt客户端实现多线程

Java死锁代码解释

java - 是否可以通过Java中的NTP客户端同步系统时钟?

C++ 如何迭代定义为父类(super class)的 vector ,但调用子类方法?

c++ - unsigned long long VS unsigned long long int

c++ - 我在 C++ 中使用 boost 哈希函数将 3 个 double 组合成一个面临冲突的哈希

java - 子线程异常

java - 使用内在锁内置于 Java 中的同步决策(好或坏)

sql-server - Elasticsearch SQL Server同步