2011-12-11 24 views
3

我有一個地圖作爲成員變量和多個訪問地圖的線程(讀寫訪問)。現在我必須確保只有一個線程可以訪問地圖。但是我怎麼點那個?什麼是最好的解決方案?C++ pthread - 如何使地圖訪問線程安全?

+0

哦,我不知道我可以/不得不接受答案,但我現在做了;) –

回答

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

在你的情況下,你可能需要一個讀寫鎖,因爲如果你有很多的讀取和很少的寫入,互斥鎖可能是矯枉過正的。

+0

提升1.36比山丘年齡大,請更新您的鏈接 –

+0

@Sam Miller,對不起,我正在看一個更老的文件。現在更新。 – Tudor

+0

1.41同樣老,我編輯你的問題使用當前版本。 –

3

您需要同步對地圖的訪問權限,例如使用POSIX mutex。該鏈接有一些簡單的例子可以說明你如何使用互斥變量。

+0

好的,我認爲使用POSIX互斥是正確的方法。謝謝! –

1

如果您有最近的編譯器,可以使用std::mutex(基於boost實現)。這是C++ 11的一部分,因此它並沒有在任何地方實現。 gcc-4.6雖然工作得很好。 底層實現是Windows中的Linux和Windows線程中的POSIX線程。