2016-08-09 1 views
1

を使用しているとき、私は のstd ::マップ

using ReqList=map<const Attrib,vector<REQ>,less<key_comp>>; // Attribには

ような値のキーおよびベクターとしてタプルの組み合わせでのstd ::マップを持っているにmutexする必要があるすべての操作/機能は何ですかタプル。これは、キーのルックアップするスレッドをマッピングし、キーが新しい場合挿入したり、すでにキーがある場合にだけ、ベクターを移入ないと

、その後のいくつかのフォームから

ReqList l; begin(l[A])=move(l[A].back()); //削除する最初の要素のように削除します値のベクトル

私は、挿入、検索、値を操作し、削除の並べ替え(最初の要素)を行っています..それでは、上記の操作または関数呼び出しはすべて相互交換される必要がありますか?私はミューテックスの下に特定のものだけを置くことができます。 std :: mapはデフォルト同期を提供しますか?

+0

スレッドがマップを共有しているときに読み書き操作を保護する必要があります。 –

+0

正直なところ、この場合、標準的なRed-Blackツリーが下にあるstd :: mapを気にしません。 MT環境では、順序マップが必要な場合は、スキップリストを参照してください。むしろ有名な[論文](http://www.cs.tau.ac.il/~shanir/nir-pubs-web/Papers/OPODIS2006-BA.pdf) いくつかの合理的な実装:https://github.com/khizmax/libcds –

答えて

1

マップから1つのスレッドが読み込まれていて、マップに別のスレッドが書き込みを行っていて、それらの操作がどのように同期されるかわからない場合は、mutexのすべてです。あなたのマップへのアクセスごとにを保護してください。標準コンテナは、あなたに保証を提供せず、同期の可能性もありません。

3

は、それは本当に、非常に簡単です: - 例えば、それらを保護することによってこれらの操作を同期させるために、あなたが「マップから」とあなたは同じ時間で「マップに書き込む」場合は、必要ミューテックス。

「マップに書き込む」とは、マップの非constメンバー関数を呼び出すことです。「マップから読み取る」とは、constメンバー関数を呼び出すことを意味します。同時に

、私はマップを書いたり、読ん可能性があることを複数のスレッドがあることを意味します。したがって、単一のスレッドプログラムは同期を必要としません。

ある時点までに地図に書き込んだら、それ以上の書き込みが行われないことが絶対確実であれば、それ以降のマップからのすべての読み取りを非同期で行うことができます。たとえば、1つのスレッドでソートのファクトリ関数でマップを設定し、設定をもう一度書き込まないと、他のスレッドはそのスレッドから非同期に読み取ることができます。スコープ外になると、デストラクタが実行され、マップが書き​​込まれることに注意してください。これが起こる前に、すべての可能な非同期読み取りが既に完了していなければなりません。

+0

ありがとうございましたjohann..clear :) –

+0

@FallingFromBedマップでのあなたの活動の一部が*かもしれないことを忘れないでください(そして、私はあなたの状況を知らないので、これを完全に避けるかもしれません)ステップ間のアクセスを許可すると、一貫性のないプログラム状態が発生する可能性があります。研究キーワード:「トランザクション処理」。 – user4581301

1

一般に、経験則として、任意のオブジェクトに対して呼び出すすべてのメソッドがconstである場合、その周囲を同期させる必要はありません。あなたがそれに対して非constをするとすぐに、あなたはそれをタッチするたびに同期する必要があります。

これは大丈夫ではありません。例えば、ある関数がconstを宣言してからconstを投げ捨てて危険なことをする、あるいはメンバーを変更可能と宣言して、 const時。また、ロックフリーのプログラミング手法を使用して、一貫性を維持して維持する必要性を避けることもできます。 【res.on.data.races]/2から

1

我々は、直接的または間接的にオブジェクト(1を変更してはならない

A C++標準ライブラリ機能を有しています。現在のスレッド以外のスレッドがアクセスできる場合は、これを含む関数の非const引数を介して直接的または間接的にオブジェクトにアクセスする場合を除きます。

だから、すべての非constメソッドは、状態を変更することが許可され、すべてのconst機能は、オブジェクトの状態を変更してはなりません。

経験則は、複数のスレッド間でデータを共有していて、少なくとも1つがライターで、同期が必要な場合です。

+0

'begin()'は状態を変更できません。 – Yakk

0
template<class T> 
struct rw_locked { 
    template<class F> 
    auto read(F&& f) const { 
    auto lock = read_lock(); 
    return std::forward<F>(f)(t); 
    } 
    auto write(F&& f) { 
    auto lock = write_lock(); 
    return std::forward<F>(f)(t); 
    } 
private: 
    auto read_lock() const { 
    return std::shared_lock<std::shared_timed_mutex>(m); 
    } 
    auto write_lock() { 
    return std::unique_lock<std::shared_timed_mutex>(m); 
    } 
    mutable std::shared_timed_mutex m; 
    T t; 
}; 

は今、単に実行します。

rw_locked< std::map< int, int > > m; 
m.read([&](auto&&m) { 
    // code to read 
}); 
m.write([&](auto&&m) { 
    // code to write 
}); 

、それが正しく、ほとんどの部分のガードのためでしょう。

技術的には、非const beginを読み取りロックで呼び出すことができます。これは定義されますが、結果のイテレータを介した書き込みは行われません。したがって、上記のコードでは、非constイテレータは取得できません。

上記のコードでmapのデータにイテレータまたはポインタを返してはいけません。そうしないと、保護されません。

関連する問題