0

データ コレクションの同期に問題があるようです。この特定のクラスには、次のようなデータ コレクション、ミューテックス、および条件変数があります。

map<std::string, double> collection;
boost::mutex collectionMutex;
boost::condition_variable collectionConditional;

ほとんどの場合、これでうまくいきます。ただし、最近、基本的にコレクション内の各値に新しい値を割り当てる関数を追加しました。コレクションには約 100 ~ 200 の値があるため、それほど多くはありません。すべての割り当ては非常に迅速に行われます。また、このステップでは計算が行われないようにしました。これは単なる一連の割り当てです。割り当てを囲むと、次のようなコードがあります(stackoverflowの回答に基づいています):

boost::mutex::scoped_lock lock(collectionMutex);
while(!lock.owns_lock())
{
    collectionConditional.wait(lock);
}
// Assignments here
collectionConditional.notify_one();

コードの他の場所には、コレクションから情報を「読み取る」関数があり、次のようになります。

double result = 0;
boost::mutex::scoped_lock lock(collectionMutex);
while(!lock.owns_lock())
{
    collectionConditional.wait(lock);
}

result = collection["Some String"];

collectionConditional.notify_one();

何が起こっているかというと、「書き込み」関数が呼び出されると、しばらくデッドロックしているように見えます。最終的には抜け出すので完全なデッドロックにはなりませんが、待ち時間が長時間(数秒)になる場合があります。これは、ミリ秒以下のオーダーである必要があります。

奇妙な部分は、以前に上記のライター関数を正常に使用したことがあり、複数のスレッドがこのデータ コレクションに問題なく書き込んでいたことです。この変更を行った理由は、このコレクションの更新を他のスレッドの実行時の状態に依存させるのではなく、1 か所に集中させるためです。

4

1 に答える 1

2

私の質問に対するコメントのおかげで、私はいくつかのことをすることになりました:

  1. 読み取り関数で operator[] を使用するのをやめ、読み取り関数を const にしました。

  2. condition_variable の使用を停止しました

  3. この他の投稿の例に基づいて shared_mutex を使用しました。

コード:

map<std::string, double> collection;
mutable boost::shared_mutex collectionMutex;

...

//Write function:
void mapData()
{
    // get upgradable access
    boost::upgrade_lock<boost::shared_mutex> lock(collectionMutex);

    // get exclusive access
    boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);

    // Assignments here.  Eg:
    // collection["Some String"] = 0.0;
}

// Read function:
double readData(std::string name) const
{
    double result = 0;
    boost::shared_lock<boost::shared_mutex> lock(collectionMutex);
    map<std::string, double>::const_iterator it = collection.find(name);
    if(it != data.end())
    {
        result = it->second;
    }
    return result;
}
于 2013-06-12T18:19:54.483 に答える