2013-07-27 139 views
0

我希望有人能在多個線程如何編寫一個共同的容器(如地圖)的建議。在某些線程可能使用Boost和C++多線程執行寫入?

地圖可能是類型共享相同的密鑰的情形:標準::地圖,用不同的線程訪問對象來修改不同數據成員。在繼續之前,每個線程是否等待當前線程執行unique_lock來完成?

會是因爲每個線程進入一個關鍵部分,因爲這例子簡單:

//somewhere within the code 
boost::unique_lock mutex; 

void modifyMap(const std::string& key,const unsigned int dataX, 
       const unsigned int dataY) 
{ 
    // would each thread wait for exclusive access? 
    boost::unique_lock<boost::shared_mutex> lock (mutex); 

    // i now have exclusive access no race conditions; 
    m_map.find(key)->second.setDataX(dataX); 
    m_map.find(key)->second.setDataX(dataY); 
} 

在此先感謝

+1

['的std :: map'](http://en.cppreference.com/w/cpp/container/map)通常*不* A ** **散列映射,但['的std :: unordered_map '](http://en.cppreference.com/w/cpp/container/unordered_map)是。 –

回答

2

您應該創建一個數據結構的線程安全的實現。它可以是基於鎖的(例如通過使用互斥鎖來實現),也可以是無鎖的(使用C++ 11和boost中支持的原子操作或內存排序)。

我簡要介紹一下基於鎖的方法。例如,你可能想要設計一個線程安全的鏈表。如果你的線程只執行讀操作,一切都是安全的。另一方面,如果您嘗試寫入此數據結構,則可能需要列表中的前一個和下一個節點指針(如果它的雙鏈接需要更新其指針以指向插入的節點)並在修改它們時某些其他線程可能會讀取不正確的指針數據,因此您需要鎖定要插入新節點的兩個節點。這會創建序列化(其他線程等待互斥體解鎖),並降低併發的可能性。

與查找表的完整的例子就是書中的「C++併發:實用多線程」可以由安東尼·威廉姆斯在171頁,其中列出6.11。由於本書的作者同時設計了boost :: thread和C++ 11線程庫,因此本書是使用最新C++標準進行多線程編程的良好開端。

更新:爲了讓您的示例適用於讀/寫(如果您還需要更多的操作來保護它們),最好使用boost :: shared_mutex,它基本上允許多讀單寫訪問:線程想要寫入,而不是獲得獨佔鎖,所有其他線程將不得不等待。以下是一些代碼:

template <typename mapType> 
class threadSafeMap { 

boost::shared_mutex map_mutex; 
mapType* m_map; 

public: 

threadSafeMap() { 
    m_map = new mapType(); 
} 


void modifyMap(std::string& key,const unsigned int dataX, 
       const unsigned int dataY) 
{ 
    //std::lock_guard in c++11. std::shared_mutex is going to be available in C++14 
    //acquire exclusive access - other threads wait 
    boost::lock_guard<boost::shared_mutex> lck(map_mutex); 

    m_map.find(key)->second.setDataX(dataX); 
    m_map.find(key)->second.setDataX(dataY); 
} 


int getValueByKey(std::string& key) 
{ 
    //std::lock_guard in c++11. std::shared_mutex is going to be available in C++11 
    //acquire shared access - other threads can read. If the other thread needs access it has to wait for a fully unlocked state. 
    boost::shared_lock<boost::shared_mutex> lck(map_mutex); 

    return m_map.getValue(key); 
} 


~threadSafeMap() { 
    delete m_map; 
} 


}; 

鎖定對象被破壞,互斥鎖在生命週期結束時解鎖。 mapType模板可以被你的地圖類型替換。

+0

感謝您的回覆,那麼我上面的示例工作?簡而言之,我只想知道訪問上述函數的多個線程是否會阻塞,直到具有獨佔訪問的線程退出(下一個線程將繼續修改地圖)。這是我正在尋找的行爲 – godzilla

+0

我添加了一些代碼。你應該使用boost :: shared_mutex,boost :: lock_guard來寫和boost :: shared_lock來讀取。如果您需要它們,其他操作應該以相同的方式進行修改。 –

+0

非常感謝Dmirty,這有助於澄清很多,只是一個問題,將升級到獨特的鎖也工作? – godzilla