2015-12-20 120 views
5

在C++ 11中是在<functional>中聲明的哈希函數類對象的線程安全嗎?例如,從多個線程調用這個函數是否安全?C++ 11 std ::哈希函數對象類線程安全

size_t hash1(const std::string& s) { 
    std::hash<std::string> str_hash; 
    return str_hash(s); 
} 

或者,如果一個人有一個全局對象std::hash<std::string> str_hash_global;,那麼它是安全調用多個線程第二個功能?

size_t hash2(const std::string& s) { 
    return str_hash_global(s); 
} 
+0

除此之外的其他考慮,確保字符串本身在計算散列值時不會被同時修改。 –

回答

6

標準庫的承諾,如果你只電話標準庫對象const -qualified成員函數,標準庫中的代碼不會導致數據爭(見[res.on.data.races ])。

標準模板std::hash,以及它的所有可允許的特化,以及滿足Hash要求任何用戶提供的算符([hash.requirements])必須具有一個const -qualified呼叫操作者由於要求,因此使用圖書館提供的std::hash專業化不應該引起競爭。而且,由於[namespace.std],程序提供的專業化必須滿足相同的要求。最後,我想你通常會通過遞歸調用const調用來使用競賽自由度保證:如果多個線程同時在地圖中查找值,則他們必須使用地圖的const接口來調用上述庫規則,但該映射只能使用hasher(或私人副本)的常量值,因此它本身只能執行無競爭散列計算。一個活潑的非常量調用操作符是否存在在這一點上是不實際的。

+0

'由於要求''必須有一個符合常規資格的呼叫操作員標準的哪個部分需要它?我一直在尋找這樣的東西,而且找不到它。有「返回的值應該只取決於程序期間的參數'k'」,但並不直接說「operator()'必須是const限定的」 –

+0

@IgorTandetnik:它說「 h'是一個(可能是'const')值「。 –

+1

啊,是的,是的。 「'h'是一個類型的值(可能是const)'H'',準確地說。我認爲仍然不嚴格地排除提供'operator()',兩個重載操作符'',一個常量操作符和一個非常量操作符的類(儘管不清楚爲什麼有人會這麼做)。 –

2

這裏適用於所有std :: lib類型的相同「線程安全」規則。

第一個版本保證是線程安全的,因爲沒有變量在線程之間共享。

如果被調用的operator()const,則第二個保證不會有任何數據競爭。除了(必需的)const之外,還沒有說明實現是否提供了hash<T>::operator()的(可能非線程安全的)非常量重載。如果你的global_str_hash是const,或者在使用它之前將它強制轉換爲const,那麼你保證會使用const operator()

沒有理由做第二個版本,它只是愚蠢的,但實際上它應該是安全的,因爲沒有標準庫實現可能會提供hash::operator()的非常規非常量超載,它們只會提供一個const超載,它必須是線程安全的。