#multithreading #c 11
Вопрос:
Я пытаюсь разработать систему, в которой у меня будет несколько потоков. Все эти потоки одновременно используют общую переменную (которая является атомной), и когда каждый поток запускается, он увеличивает эту переменную, а перед завершением этого потока уменьшает эту переменную. Я хотел бы, чтобы поток блокировался, если текущее значение этой переменной превышает определенное предельное значение. Простой psuedocode таков:
std::atomic<int> var;
int limit = 3; //limit value
void doWork() //This method is run as multiple thread simultaneously
{
if(var.load() < limit)
{
//block until this condition is met
}
//increment
var ;
//Do some work
.....
//Decrement before leaving
var--
}
Теперь мне на ум приходят два подхода. Первый подход-спать во время var.load < limit
сна, но это выглядит неоптимальным. Второй подход заключается в использовании conditional_variable
. Я использую этот подход ниже, но я считаю, что здесь у меня есть две проблемы
- Первый поток будет заблокирован при cv.wait(lk, []{возврат var.load() ;
- Несколько потоков не будут выполнять работу, только один будет выполнять работу, в то время как другие будут заблокированы.
Я был бы признателен, если бы кто-нибудь мог подсказать, как я могу удалить эти дефекты из приведенного ниже кода, или если есть лучший подход ?
std::condition_variable cv;
std::mutex cv_m;
std::atomic<int> var;
int limit = 3; //limit value
void doWork()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting... n";
cv.wait(lk, []{
return var.load() < limit
});
//Increment var
var ;
//Do some Work
...
//Decrement Work
var--
cv.notify_all();
}
Комментарии:
1. Поведение, которое вы описываете, очень похоже на поведение семафора: en.m.wikipedia.org/wiki/Semaphore_(программирование)
2. Вы должны разблокировать после
var
и до «Выполнения некоторой работы». И нет, первый поток не будет блокировать — вспомните, чтоcondition_variable::wait
на самом деле не ждет, если предикат уже удовлетворен; он ждет только в том случае, если он ложен, и до тех пор, пока он не станет истинным.