2011-01-11 63 views
1

我有一個unordered_map的unordered_map,它存儲了一個對象的指針。無序的地圖由多個線程共享。我需要迭代每個對象並執行一些耗時的操作(如通過網絡發送等)。我怎麼能鎖定多個unordered_map,以便它不會阻塞太久?對鎖內的STL容器執行耗時的操作

typedef std::unordered_map<string, classA*>MAP1; 
typedef std::unordered_map<int, MAP1*>MAP2; 
MAP2 map2; 
pthread_mutex_lock(&mutexA) //how could I lock the maps? Could I reduce the lock granularity? 
for(MAP2::iterator it2 = map2.begin; it2 != map2.end; it2++) 
{ 
    for(MAP1::iterator it1 = *(it2->second).begin(); it1 != *(it2->second).end(); it1++) 
    { 
    //perform some time consuming operation on it1->second eg 
    sendToNetwork(*(it1->second)); 
    } 
} 
pthread_mutex_unlock(&mutexA) 

回答

0

您可以將所有這些對象存儲在像List這樣的其他結構中並進行迭代,因此您不必鎖定地圖。

您也可以嘗試創建數據的副本並在副本上工作 - 這樣可以在副本處理時修改地圖。

0

看看dr dobbs上的article by herb sutter,專門解決您的問題。

一般的想法是有一個線程內部封裝資源的對象。線程接受對資源執行操作的請求,允許調用者推送請求,然後繼續執行,並讓內部線程執行請求。

此外,你會被建議使用boost.thread而不是直接pthread,它是遠不那麼痛苦。

0

通常,長時間持有互斥鎖並不是一個好習慣。這裏已經提到的一種常見方法是有一個對象隊列,它將讀取並處理工作線程中的對象。

在您的例子mutexA是保護MAP2從當你迭代它被修改,你可以做這樣的事情:

std::vector<MAP1*> map1Queue; 
pthread_mutex_lock(&mutexA); 
for(MAP2::iterator it2 = map2.begin; it2 != map2.end; ++it2) { 
    map1Queue.push_back(it2->second); 
} 
pthread_mutex_unlock(&mutexA); 
// Now you can process objects from map1Queue in worker thread 

唯一的問題是,你需要保證MAP1 *仍然會有效的,也許使用噓:: shared_ptr而不是raw_pointers。

+0

如果某些map2項目在解鎖後被抹去會發生什麼? – 9dan 2011-01-11 08:11:30