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