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

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

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

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

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

0

Решение

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

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

Другие решения

Других решений пока нет …