0

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

提前致谢

4

1 回答 1

2

您应该创建数据结构的线程安全实现。它可以是基于锁的(例如通过使用互斥锁实现)或无锁的(使用 C++11 和 boost 支持的原子操作或内存排序)。

我可以简要描述一下基于锁的方法。例如,您可能想要设计一个线程安全的链表。如果您的线程只执行读取操作,那么一切都是安全的。另一方面,如果您尝试写入此数据结构,您可能需要列表中的上一个和下一个节点指针(如果它是双链接的,您需要更新它们的指针以指向插入的节点)并且在您修改它们时其他一些线程可能会读取不正确的指针数据,因此您需要锁定要在其间插入新节点的两个节点。这会创建序列化(其他线程等待互斥锁被解锁)并减少并发的可能性。

带有查找表的完整示例可在 Anthony Williams 所著的“C++ 并发:实用多线程”一书的第 171 页,清单 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;
}


};

Lock-guard 对象被破坏,互斥锁在生命周期结束时被解锁。mapType 模板可以替换为您的地图类型。

于 2013-07-27T14:27:01.190 回答