我怎样才能使共享对象的访问成为线程安全的?

     2023-02-22     208

关键词:

【中文标题】我怎样才能使共享对象的访问成为线程安全的?【英文标题】:How could I make the access of commonly shared object thread-safe? 【发布时间】:2018-04-03 23:12:23 【问题描述】:

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

【问题讨论】:

除了在logger 上调用log 之外,其他线程还能做什么? 除了记录之外没什么。一旦Logger logger 被主线程实例化;它将通过引用传递给需要日志记录功能的其他线程。其他线程除了使用log方法外,并没有做太多的事情 那么 - 没什么好担心的。您已经提供的一种解决方案 - 在记录器中添加互斥锁作为成员并保护其日志功能。其他解决方案是用同步记录器包装非同步记录器 - 具有互斥锁和记录器的类(可能的参考)。 抱歉,能否详细说明同步记录器? “我知道资源共享可以通过使用互斥锁和信号量等同步机制实现线程安全,但我的问题不同。”是吗? “最好的方法是什么?”不是 *** 类型的问题。 【参考方案1】:

更符合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 syncLoggerlogger;

   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();

【讨论】:

感谢您的回答。这将如何解决问题?当多个线程访问SynchronizedLogger sLogger 对象时,仍然会有竞争条件,对吧?因为SynchronizedLogger sLogger 仍然是一个没有被任何同步锁包裹的共享资源?如果我错了,请纠正我。 不,如果它的构造发生,则不是。在所有客户端线程启动之前在主线程中,并且在所有线程停止后发生销毁。

UICollectionView 太宽。我怎样才能使它成为设备的宽度?

】UICollectionView太宽。我怎样才能使它成为设备的宽度?【英文标题】:UICollectionViewistoowide.Howcanimakeitthewidthofthedevice?【发布时间】:2015-05-2800:33:11【问题描述】:我在情节提要中创建了一个新的UICollectionView。我的问题是单元格... 查看详情

我怎样才能使它成为一个更好的递归动画 jQuery 脚本?

】我怎样才能使它成为一个更好的递归动画jQuery脚本?【英文标题】:HowcanImakethisabetterrecursiveanimatedjQueryscript?【发布时间】:2011-06-0819:45:30【问题描述】:这个想法是为云div设置动画,并让它永久地在水平方向上来回动画。这... 查看详情

java示例代码_同步可以与条件语句一起工作吗?我怎样才能使这段代码性能和线程安全

java示例代码_同步可以与条件语句一起工作吗?我怎样才能使这段代码性能和线程安全 查看详情

Api 将日期时间作为数字返回,我怎样才能使它成为正确的日期?

】Api将日期时间作为数字返回,我怎样才能使它成为正确的日期?【英文标题】:Apireturnsdate-timeasnumbershowcanImakeitaproperdate?【发布时间】:2020-07-0318:17:02【问题描述】:我正在使用一个外部api(使用MongoDB),它向我发送这样的日... 查看详情

我怎样才能使评论中的标记用户成为该用户主页的超链接? (姜戈)

】我怎样才能使评论中的标记用户成为该用户主页的超链接?(姜戈)【英文标题】:HowcouldImaketaggeduserinthecommentahyperlinktothatuser\'shomepage?(Django)【发布时间】:2014-10-0522:46:10【问题描述】:就像facebook一样,如果我在评论中标记... 查看详情

如何使应用程序线程安全?

...我特别认为线程安全意味着它必须满足多个线程访问相同共享数据的需求。但是,这个定义似乎还不够。任何人都可以列出为使应用程序线程安全而要完成或需要注意的事情。如果可能,请给出关于C/C++语言的答案。【问题讨论... 查看详情

对象的共享

1.volidate关键字:volidate关键字可以保证多线程程序使用共享且可变的long和double等类型的变量是安全的,非volidate类型则会不安全。Java语言提供一种稍弱的同步机制,即volidate变量,用来确保将变量的更新操作通知到其他线程。在... 查看详情

我正在使用 jQuery 进行图像预览。但是我无法发布预览后单击的数据。我怎样才能使它成为现实?

...ery进行图像预览。但是我无法发布预览后单击的数据。我怎样才能使它成为现实?【英文标题】:I\'mdoinganimagepreviewwithjQuery.ButIcannotpostthedataIclickedafterpreview.HowCanIMakeItReal?【发布时间】:2021-04-0312:29:27【问题描述】:$(document).ready... 查看详情

Java:使所有字段成为最终字段或可变字段?

...:2019-05-1307:13:04【问题描述】:如果我有一个在线程之间共享的对象,在我看来,每个字段都应该是final或volatile,原因如下:如果该字段应该改变(指向另一个对象,更新原始值),那么该字段应该是volatile,以便所有其他线程... 查看详情

线程安全策略(代码片段)

...限制的对象,由线程独占,并且只能被占有它的线程修改共享只读:一个共享只读的对象,在没有额外同步的情况下,可以被多个线程并发访问,但是任何线程都不能修改它线程安全对象:一个线程安全的对象或者容器,在内部... 查看详情

通过线程共享指针的 std::vector

...线程都应该能够获取或删除指针并将其从向量中删除。我怎样才能使这个线程安全,C++标准库中是否有任何东西可以做到这一点?【问题讨论】:欢迎来到***!请查看HowtoAsk。如果您包含您 查看详情

java并发编程实战03对象的共享

...同步多个线程避免同一时刻访问相同数据,本篇介绍如何共享和发布对象,使它们被安全地由多个进程访问。1.可见性通常,我们无法保证执行读操作的线程能看到其他线程写入的值,因为每个线程都由自己的缓存机制。为了确... 查看详情

鼠标拖动选择不适用于触摸设备。我怎样才能使它成为可能?

】鼠标拖动选择不适用于触摸设备。我怎样才能使它成为可能?【英文标题】:Themousedragselectiondoesnotworkontouchdevices.HowcanImakeitpossible?【发布时间】:2016-02-2907:27:02【问题描述】:鼠标拖动选择不适用于触控设备。我该如何解决这... 查看详情

进程间通信:共享内存与线程对象访问

】进程间通信:共享内存与线程对象访问【英文标题】:Interprocesscommunication:Sharedmemoryvsthreadobjectaccess【发布时间】:2014-02-2508:28:19【问题描述】:我一直都知道,共享内存是在两个线程之间共享数据的最快方式(例如http://www.boo... 查看详情

线程共享数据的安全问题

...程是不能执行的,只能等待带锁的线程执行完拿到同步锁才能进入同步代码块中执行。举个例 查看详情

如何使字典 NSDictionary 成为阅读、插入的线程安全?

】如何使字典NSDictionary成为阅读、插入的线程安全?【英文标题】:HowtomakedictionaryNSDictionarybethreadsafeforreading,inserting?【发布时间】:2015-01-1012:59:34【问题描述】:在应用程序的每次启动时,我都必须从服务器获取几个.plist,然... 查看详情

在java中arraylist如何保证线程安全

[b]保证线程安全的三种方法:[/b]不要跨线程访问共享变量使共享变量是final类型的将共享变量的操作加上同步一开始就将类设计成线程安全的,比在后期重新修复它,更容易.编写多线程程序,首先保证它是正确的,其次再考虑性能.无... 查看详情

线程安全性

...的代码,核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问。“共享”意味着变量可以由多个线程同时访问,“可变”意味着变量的值在其生命周期内可以发生变化什么是线程安全性?当多个线程访问某... 查看详情