[英]Best way to control access to a string object in multi-threaded program
我有一個“ config”類,其中包含一堆用於“鏡像”配置設置的屬性。 該類的單個實例在整個代碼中共享(使用boost shared_ptr對象),並且其屬性由多個線程(大約100個)讀取。
有時,設置可能會更改,並且“監視”線程會更新對象中的適當屬性。
對於整型和布爾型屬性,我使用的是Boost原子,以便在發生更新且監視線程設置該值時,所有讀取線程均不會以部分更新的狀態讀取該值。
但是,對於字符串屬性,我擔心使它們成為原子屬性會嚴重損害性能。 這樣做的一個好方法似乎是讓字符串屬性實際上是指向字符串的指針,然后在發生更新時,可以構建一個新的字符串對象,然后寫入共享對象(字符串指針)。只會寫入要指向的新字符串對象的地址。 因此,我認為寫時間將比將整個新字符串值寫到共享字符串對象要短得多。
但是,這樣做意味着我認為我想對字符串屬性使用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";
}
那是矯kill過正嗎? 有更好的方法嗎? 我真的不喜歡讀取線程必須通過解引用並調用.load()來訪問該值的方式。 另外,它甚至是線程安全的,還是這些東西實際上否定了atomic和/或shared_ptr類型的安全功能?
我知道我可以使用互斥鎖並在“ getter”中訪問時讀取鎖定,並在監視線程更新字符串的值時寫入鎖定,但是我想避免這種情況,因為我試圖使config類保持簡單它將有數十個,可能數百個這些字符串屬性。
在此先感謝您的任何建議/信息!
您已經在為每個使用者提供一個shared_ptr到配置對象。 因此,線程不會注意到配置對象是否始終不是同一對象。
也就是說,當主要配置更改時,生成一個全新的配置對象。 這似乎是很多復制,但是我敢打賭,這種情況很少發生,您不會注意到開銷。 然后,您可以將新的配置對象替換為舊的配置對象,並且當舊對象的所有使用方都用完它時,它將消失。
顯然,這改變了使用配置對象的語義。 希望能夠注意到配置更改的長時間運行的線程將必須定期刷新其配置對象。 最簡單的方法就是在每次使用配置數據時獲取一個新的配置對象。 同樣,除非您在硬循環中使用配置字符串,否則這不太可能太昂貴。
從好的方面來說,您可以使整個配置對象const
,這可能允許一些優化。
使用互斥變量來設置共享資源(這里是字符串對象)的鎖定的經典方法不僅是處理此類情況的最佳方法,而且是最有效的方法,否則您可能會因為保護不完善而陷入困境,或者最終解決方案的開銷更大。 在某些應用程序中,可以通過對單獨的對象使用單獨的互斥鎖來提高效率,這樣,如果一個對象正在更新,則其他對象仍然可以訪問。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.