我有一个地图作为成员变量和多个访问地图的线程(读写访问)。现在我必须确保只有一个线程可以访问地图。但是我怎么点那个?什么是最好的解决方案?C++ pthread - 如何使地图访问线程安全?
3
A
回答
1
实际上,在给定的时间只有一个线程应该访问map
的前提略微偏离。
并发读取是可以的,你想避免的是有一个线程修改地图,而其他人正在阅读它。
根据您所需的粒度级别,您可能会考虑使用读写器锁定,这会使多个读取操作并行进行。
具体用法是用升压证明here:
boost::shared_mutex _access;
void reader()
{
// get shared access
boost::shared_lock<boost::shared_mutex> lock(_access);
// now we have shared access
}
void writer()
{
// get upgradable access
boost::upgrade_lock<boost::shared_mutex> lock(_access);
// get exclusive access
boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
// now we have exclusive access
}
之后,它仅仅是一个方便的包装地图接入问题。例如,你可以使用一个通用的代理结构:
template <typename Item, typename Mutex>
class ReaderProxy {
public:
ReaderProxy(Item& i, Mutex& m): lock(m), item(i) {}
Item* operator->() { return &item; }
private:
boost::shared_lock<Mutex> lock;
Item& item;
};
template <typename Item, typename Mutex>
class WriterProxy {
public:
WriterProxy(Item& i, Mutex& m): uplock(m), lock(uplock), item(i) {}
Item* operator->() { return &item; }
private:
boost::upgrade_lock<Mutex> uplock;
boost::upgrade_to_unique_lock<Mutex> lock;
Item& item;
};
而且你可以用它们为:
class Foo {
typedef ReaderProxy< std::map<int, int>, boost::shared_mutex> Reader;
typedef WriterProxy< std::map<int, int>, boost::shared_mutex> Writer;
public:
int get(int k) const {
Reader r(map, m);
auto it = r->find(k);
if (it == r->end()) { return -1; }
return it->second;
}
void set(int k, int v) {
Writer w(map, m);
w->insert(std::make_pair(k, v));
}
private:
boost::shared_mutex m;
std::map<int, int> map;
};
迭代器要小心的是,他们只能当互斥锁由持有安全地操纵当前线程。另外,我建议您严格控制地图,使其适合有意义的最小对象,并只提供您需要的操作。最少的方法可以访问地图,越不可能错过一个访问点。
4
Boost包含一些用于共享访问的很好的锁定实现。看看documentation。
在你的情况下,你可能需要一个读写锁,因为如果你有很多的读取和很少的写入,互斥锁可能是矫枉过正的。
3
1
如果您有最近的编译器,可以使用std::mutex
(基于boost实现)。这是C++ 11的一部分,因此它并没有在任何地方实现。 gcc-4.6虽然工作得很好。 底层实现是Windows中的Linux和Windows线程中的POSIX线程。
相关问题
- 1. 线程安全地访问类成员
- 2. 线程安全访问数组和线程安全访问
- 3. 使字典访问线程安全?
- 4. 如何以线程安全的方式访问c#WPF控件?
- 5. 线程安全访问静态集合
- 6. Windows窗体:线程安全访问GUI?
- 7. 如何优雅地访问线程安全的收集和使用的AutoResetEvent
- 8. Restful API:如何安全地访问api?
- 9. 正在访问BufferedImage线程安全
- 10. 线程安全与类访问器
- 11. 访问MDF文件线程安全
- 12. WinForms线程安全控制访问
- 13. 锁定/线程安全访问XObject
- 14. QVector预分配访问线程安全
- 15. thread_specific_ptr线程安全的访问
- 16. 访问Qt窗口线程安全
- 17. 线程安全get(访问器方法)
- 18. 如何安全地破坏C++中的Posix线程池
- 19. C#线程安全
- 20. 如何使线程安全,而不是线程安全
- 21. 如何安全地停止std线程?
- 22. 如何安全地退出线程
- 23. 如何安全地关闭线程?
- 24. 如何安全地阻止.NET线程
- 25. 安全地取消线程
- 26. 如何在多线程环境下安全地访问struct字段?
- 27. C#:datatable线程安全问题
- 28. C#中线程安全的数据库访问#
- 29. C++:一个作家/多读者访问unordered_map线程安全吗?
- 30. 将Java NIO Files.walkFileTree访问移植到C,维护线程安全
哦,我不知道我可以/不得不接受答案,但我现在做了;) –