2011-12-11 9 views
3

私はメンバ変数としてマップを持ち、マップにアクセスする複数のスレッド(読み書きアクセス)を持っています。今では、1つのスレッドだけがマップにアクセスできるようにする必要があります。しかし、私はそれをどのように点けますか?そのための最良の解決策は何ですか?C++ pthread - マップアクセスをスレッドセーフにするには?

+0

オハイオ州私は答えを受け入れる必要があることを知らなかったが、私は今それをした;) –

答えて

1

実際には、特定の時間に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 
} 

その後、それは便利マップへのアクセスをラップするだけです。ミューテックスがで保持されている間、彼らは唯一の安全に操作することができ、しかしイテレータの用心

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; 
}; 

:たとえば、汎用プロキシ構造使用することができます

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; 
}; 

をそして、あなたは、それらを使用することができます現在のスレッド。

また、マップを厳格に管理し、意味のある最小のオブジェクトに合わせて、必要な操作だけを提供することをお勧めします。最小限の方法で地図にアクセスできれば、アクセスポイント1つを逃す可能性は低くなります。

4

Boostには、共有アクセス用の素晴らしいロック実装が含まれています。 documentationをご覧ください。

多くの場合、読み取りと書き込みが非常に少ない場合は、相互排他ロックがおそらく過剰なので、おそらく読み書きロックが必要です。

+0

ブースト1.36は丘より古い。 –

+0

@Sam Miller、申し訳ありません、私は古い資料。今更新されました。 – Tudor

+0

1.41も同様に古いですが、あなたの質問を編集して現在のリリースを使用しています。 –

3

POSIX mutexを使用するなど、マップへのアクセスを同期する必要があります。このリンクには、相互排除変数の使用方法の例をいくつか簡単に説明しています。

+0

私はPOSIXミューテックスを使うのが正しい方法だと思います。ありがとうございました! –

1

最新のコンパイラを使用している場合は、std::mutex(これは拡張実装に基づいています)を使用できます。これはC++ 11の一部なので、どこにでも実装されていません。 gcc-4.6はかなりうまく動作します。 基礎となる実装は、WindowsのlinuxおよびWindowsスレッドのPOSIXスレッドです。

関連する問題