Повысить scoped_lock. Будет ли этот замок?
решена
Я изменил очередь bfs::directory_iterator на очередь std::string и неожиданно решил проблему.
Привет, у меня есть чувство, что я делаю что-то не так.
Я реализовал (или попытался) шаблон пула потоков.
N темы читаются из очереди, но у меня возникли некоторые проблемы. Вот что я получил:
//inside a while loop
bool isEmpty;
bfs::directory_iterator elem;
{
boost::mutex::scoped_lock lock(this->queue_mutex);
isEmpty = this->input_queue.isEmpty();
if (!isEmpty){
elem= *(this->input_queue.pop());
}
else{
continue;
}
}
Будет ли scoped_lock работать внутри тела if? Я начинаю верить, что это не так (после выполнения многих тестов). Если нет, есть ли какой-либо ограниченный способ сделать это (то есть не явный способ разблокировки блокировки)
Заранее спасибо.
Обновить
Код, который добавляет элементы в очередь, выглядит следующим образом
//launches the above code, passing a reference to mutex and queue.
Threads threads(queue,queue_mutex);
for (bfs::directory_iterator dir_it:every file in directory){
boost::mutex::scoped_lock lock(queue_mutex);
queue.push(dir_it);
}
Я помещаю cout для управления всплывающим именем файла, и если я нажимаю 2 файла (file1) и (file2) и использую 2 потока, я получаю оба файла "file2".
class Threads{
boost::thread::thread_group group;
Thread (N){
//also asigns a reference to a queue and a mutex.
for(i 1..N){
//loop is posted above.
group.add(new boost::thread(boost::bind(&loop,this)));
}
}
};
3 ответа
Выложенный код выглядит хорошо - если вы видите проблемы, может быть, есть какое-то другое место, где блокировка должна быть взята, а ее нет (например, код, который добавляет что-то в очередь).
Нет, замок не будет работать, если он перемещен внутри if
потому что на чеке против пустоты будет состояние гонки. Последний элемент мог быть удален между проверкой и блокировкой.
Я бы добавил блокировку в очередь... управление блокировками, внешними по отношению к очереди, является сложным, имеет тенденцию вводить в заблуждение код, но также является достаточно хрупким, поскольку открытая структура данных является открытой.
Шаблон, который выглядит как утилита сбора для очередей, представляет собой метод try_pop & try_push. Parallel Extensions to .NET использует этот шаблон с System.Collections.Concurrent.ConcurrentQueue.
Это делается либо с помощью очереди без блокировки, либо путем простого внедрения очереди и блокировки в контейнер с соответствующими интерфейсами. У Энтони Уильямса есть хороший пост о том, как сделать это с помощью std::queue здесь.
ваш код может выглядеть так:
//inside a while loop
bfs::directory_iterator elem;
while (this->input_queue.pop(*elem))
{
... // do something
}