2013-07-27 141 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