我目前有一個程序,它具有緩存機制。我有一個線程監聽從另一個服務器到這個緩存的更新。該線程在收到更新時將更新緩存。下面是一些僞代碼:更新緩存而不會阻止
void cache::update_cache()
{
cache_ = new std::map<std::string, value>();
while(true)
{
if(recv().compare("update") == 0)
{
std::map<std::string, value> *new_info = new std::map<std::string, value>();
std::map<std::string, value> *tmp;
//Get new info, store in new_info
tmp = cache_;
cache_ = new_cache;
delete tmp;
}
}
}
std::map<std::string, value> *cache::get_cache()
{
return cache_;
}
cache_
正在從許多不同的線程讀取兼任。我相信我是如何擁有它的,如果我的一個線程調用get_cache()
,然後我的緩存更新,然後線程嘗試訪問存儲的緩存,我將遇到未定義的行爲。
我正在尋找一種方法來避免此問題。我知道我可以使用互斥鎖,但是我寧願不阻止讀取,因爲它們必須儘可能低延遲,但如果需要,我可以走這條路。
我在想這是不是一個unique_ptr的好用例。我的理解是正確的:如果一個線程調用get_cache,並且返回一個unique_ptr而不是一個標準指針,那麼一旦所有具有舊版本緩存的線程都完成了它(即保留範圍),該對象將被刪除。
使用unique_ptr這種情況下的最佳選擇,還是有另一種選擇,我沒有想到?
任何輸入將不勝感激。
編輯:
我相信我在我的OP中犯了一個錯誤。我的意思是使用並傳遞一個shared_ptr而不是cache_的unique_ptr。當所有線程都完成cache_時,shared_ptr應該刪除它自己。
有關我的程序:我的程序是一個網絡服務器,將使用這些信息來決定返回什麼信息。這是相當高的吞吐量(數千次請求/秒)每個請求查詢緩存一次,所以告訴我的其他線程何時更新沒有問題。我可以容忍稍微過時的信息,並希望在可能的情況下阻止我的所有線程執行。緩存中的信息相當大,因此我想限制任何有價值的副本。
update_cache
只運行一次。它運行在只監聽更新命令並運行代碼的線程中。
使用[讀者,作家鎖(http://en.wikipedia.org/wiki/Readers-writer_lock)。 [升壓提供酮](http://stackoverflow.com/questions/989795/example-for-boost-shared-mutex-multiple-reads-one-write/6450576#6450576)。此外,您可能能夠使用[從此處](http://stackoverflow.com/a/22492335/1074413)使用RCU的相同建議也適用。 –
儘管如此,如果可能的話,我想避免阻塞。使用唯一指針會導致某種未定義的行爲嗎?讀/寫鎖是否是一個更好的解決方案是否有原因?另外一個說明,我可以容忍稍微過時的信息。 – Eumcoz
我想我在這裏的處境實際上與設計有關,而不是實現。首先,'unique_ptr'看起來不起作用,因爲只有一個線程合法地可以保存'unique_ptr',這使得可以訪問緩存的多個線程失效。即使你可以解決這個問題,客戶端線程如何知道他們需要更新?我覺得你的緩存應該暴露一個接口,而不是僅僅在客戶端上傾倒實際的緩存指針,並讓它們瘋狂運行。如果您可以讓客戶端查詢緩存,那麼類似RCU的方法可能是完美的 - 零開銷讀取! –