我希望有人可以建议多个线程如何写入公共容器(例如地图)。在一些情况下,某些线程可能使用Boost和C ++共享相同的密钥
映射可能是类型:std :: map,其中不同的线程访问对象以修改不同的数据成员。在继续之前,每个线程是否会等待当前线程完成时遇到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);
}
提前致谢
答案 0 :(得分:2)
您应该创建数据结构的线程安全实现。它可以是基于锁的(例如通过使用互斥锁实现)或无锁(使用C ++ 11和boost中支持的原子操作或内存排序)。
我可以简要介绍一下基于锁的方法。例如,您可能想要设计一个线程安全的链表。如果您的线程只执行读操作,则一切都是安全的。另一方面,如果您尝试写入此数据结构,则可能需要列表中的上一个和下一个节点指针(如果其双链接您需要更新其指针以指向插入的节点)并在修改它们时某些其他线程可能会读取不正确的指针数据,因此您需要锁定要插入新节点的两个节点。这会创建序列化(其他线程等待互斥锁被解锁)并降低并发的可能性。
有关查找表的完整示例可在Anthony Williams的第171页“C ++ Concurrency:Practical Multithreading”一书中找到,列于第6.11页。本书本身是使用最新C ++标准进行多线程编程的良好开端,因为本书的作者还设计了boost :: thread和C ++ 11线程库。
更新:使您的示例适用于读/写(如果您还需要更多操作以保护它们),最好使用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模板可以替换为您的地图类型。