多个线程执行写入?

时间:2013-07-27 14:04:06

标签: c++ multithreading boost

我希望有人可以建议多个线程如何写入公共容器(例如地图)。在一些情况下,某些线程可能使用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);
}

提前致谢

1 个答案:

答案 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模板可以替换为您的地图类型。