2015-01-27 41 views
0

我有一个“配置”类,它有一堆“镜像”配置设置的属性。该类的单个实例在整个代码中共享(使用boost shared_ptr对象),并由多个线程(大约100)读取其属性。在多线程程序中控制对字符串对象的访问的最佳方法

偶尔,设置可能会更改,并且“监视器”线程会更新对象中的相应属性。

对于整数和布尔属性,我使用boost原子,以便当发生更新并且监视线程设置该值时,读取的线程都不会以部分更新的状态读取它。

但是,对于字符串属性,我担心让它们原子化会显着地损害性能。这似乎是一个很好的方法,可以让字符串属性实际上是指向字符串的指针,然后当更新发生时,可以创建一个新的字符串对象,然后写入共享对象(字符串指针)只会写入新字符串对象的地址以指向。所以我认为写入时间比写一个全新的字符串值到共享字符串对象要短得多。

但是,这样做意味着我想要为字符串attribs使用shared_ptrs,以便一旦所有读取线程都使用更新后的字符串指针属性,就会自动删除保存前一个值的字符串对象。

因此,要举一个例子:

class Config 
{ 
    public: 
    boost::atomic<boost::shared_ptr<std::string> > configStr1; 

    void updateValueInMonitorThread(std::string newValue) 
    { 
     boost::shared_ptr<string> newValuePtr; 
     newValuePtr = newValue; 
     configStr1 = newValuePtr; 
    } 
}; 

void threadThatReadsConfig(boost::shared_ptr<Config> theConfig) 
{ 
    std::map<std::string, std::string> thingImWorkingOn; 
    thingImWorkingOn[*(theConfig->configStr1.load())] = "some value"; 
} 

那是大材小用?有没有更好的方法来做到这一点?我真的不喜欢读取线程通过取消引用并调用.load()来访问值的方式。此外,它甚至是线程安全的,还是这些东西实际上否定了atomic和/或shared_ptr类型的安全特性?

我知道我可以使用互斥锁并在“getter”中访问时读锁定,并在监视器线程更新字符串值时写入锁定,但我想避免这种情况,因为我试图保留配置类很简单,它会有几十个,可能有数百个这样的字符串属性。

在此先感谢您的任何建议/信息!

回答

1

您已经为每个使用者提供了一个shared_ptr给配置对象。因此,如果配置对象不总是相同的对象,线程将不会注意到。

也就是说,当主配置发生变化时,会生成一个全新的配置对象。这似乎很多复制,但我敢打赌,它发生的情况很少,你不会注意到开销。然后,您可以交换旧配置对象中的旧配置对象,并且旧对象的所有使用者完成配置时,它将消失。

很明显,这改变了使用配置对象的语义。想要能够注意到配置更改的长时间运行的线程将不得不定期刷新其配置对象。最简单的方法就是在每次使用配置数据时获取新的配置对象;再次,这不太可能太昂贵,除非您在硬循环中使用配置字符串。

另一方面,您可以使整个配置对象const,这可能允许一些优化。

0

使用互斥变量设置共享资源的锁(在这里你的字符串对象)的经典方法,不仅是最好的,但处理这种情况的最有效的方式,否则你可能会遇到麻烦,因为不完整的保护或您最终可能会遇到更多开销的解决方案。在某些应用中,你可以通过使用单独的互斥锁单独的对象,因此,如果一个对象被更新,其他人仍然可以访问提高工作效率。

相关问题