2016-10-30 3 views
3

Я отправляю несколько заданий в threadpool, а затем жду, пока он закончит. Мне интересно, если я что-то пропустил, потому что иногда мои рабочие потоки замерзают.Безопасно ли использование этого потока?

Мой основной поток запустить рабочих, как это:

numJobsPosted = 0; 
for(auto entry : list) 
{ 
    numJobsPosted++; 
    threadPool->post(std::bind(&Controller::workerFunc, this, entry)); 
} 

std::unique_lock<std::mutex> lock(m_workerLock); 
while(numJobsPosted > 0) 
{ 
    m_workerCondition.wait(lock); 
} 

Теперь мой workerFunc выглядит примерно так:

void Controller::workerFunc(Entry entry) 
{ 
    // do some work with entry 

    // notify finished 
    numJobsPosted--; 
    if(numJobsPosted <= 0) 
    { 
     // does the look need to be around the numJobsPosted-- ? 
     std::unique_lock<std::mutex> locker(m_workerLock); 
     m_workerCondition.notify_one(); 
    } 
} 

ли выше код безопасным, или мне нужно сделать, чтобы поставить замок вокруг оператор декремента?

ответ

2

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

numJobsPosted--; 

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

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

numJobsPosted++; 

и эта линия в workerFunc:

numJobsPosted--; 

Чтобы сделать его безопасным, вы можете, например, сделать numJobsPosted атомными, например объявить, как это (в C++ 11):

#include <atomic> 
std::atomic_int numJobsPosted; 

Оформление workerFunc что-то вроде этого:

void Controller::workerFunc(Entry entry) 
{ 
    // do some work with entry 

    // notify finished 
    { 
     std::unique_lock<std::mutex> locker(m_workerLock); 
     numJobsPosted--; 
     if(numJobsPosted <= 0) 
     { 
      m_workerCondition.notify_one(); 
     } 
    } 
} 

может решить первую гонку условие случай, но не второй.

(Кроме того, я не очень понимаю логику вокруг манипуляции и тестирования вы делаете на numJobsPosted, но я думаю, что это рядом с точкой вашего вопроса)

+0

Да так numJobsPosted был регулярным ИНТ, я Я изменю его, чтобы он был атомарным. О коде, который вы опубликовали, я, конечно же, должен уменьшить numJobsPosted, даже если он больше 1, я предполагаю, что сейчас просто заблокирую замок вокруг оператора. Благодарю. –

+0

Хорошо, я отредактирую код соответственно для ясности –

Смежные вопросы