我有一個地圖作爲成員變量和多個訪問地圖的線程(讀寫訪問)。現在我必須確保只有一個線程可以訪問地圖。但是我怎麼點那個?什麼是最好的解決方案?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,維護線程安全
哦,我不知道我可以/不得不接受答案,但我現在做了;) –