2015-01-27 49 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

使用互斥變量設置共享資源的鎖(在這裏你的字符串對象)的經典方法,不僅是最好的,但處理這種情況的最有效的方式,否則你可能會遇到麻煩,因爲不完整的保護或您最終可能會遇到更多開銷的解決方案。在某些應用中,你可以通過使用單獨的互斥鎖單獨的對象,因此,如果一個對象被更新,其他人仍然可以訪問提高工作效率。

相關問題