Один Писатель Много Читателей выпускают для карты

Кажется, у меня возникла проблема с синхронизацией сбора данных. В этом конкретном классе у меня есть переменная сбора данных, мьютекса и условия, которая выглядит примерно так:

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

По большей части это работает. Однако недавно я добавил функцию, в которой я назначаю новое значение каждому значению в коллекции. В коллекции около 100-200 значений, так что не очень много; все задания выполняются очень быстро. Я также позаботился о том, чтобы на этом этапе не происходило никаких вычислений, это всего лишь серия заданий. Вокруг назначений у меня есть код, который выглядит следующим образом (на основе ответа здесь на stackru):

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();

Происходит следующее: когда вызывается моя функция write, она на некоторое время блокируется. Это в конечном итоге вырывается, поэтому это не полный тупик, но период ожидания может быть долгим (несколько секунд). Это должно быть порядка миллисекунд или меньше.

Странно то, что я успешно использовал вышеописанную функцию записи раньше, и несколько потоков записывали в эту коллекцию данных без проблем. Причина, по которой я сделал это изменение, - это перемещение централизованных обновлений этой коллекции в одно место, вместо того, чтобы оно зависело от состояния времени выполнения других потоков.

1 ответ

Решение

Благодаря комментариям на мой вопрос, я сделал несколько вещей:

  1. Прекратил использование оператора [] в функции чтения и сделал функцию чтения постоянной.

  2. Прекращено использование условия

  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;
}
Другие вопросы по тегам