(повышение) издержек unique_lock при использовании с условной_вариабельной

почему wait() метод boost::conditiona_variable требовать boost::unique_lock объект как параметр, а не простой boost::mutex?

На самом деле, не совсем понятно назначение unique_lock. Почему я должен создать еще один объект-обертку вокруг моего boost::mutexи как это влияет на производительность?

Например, предположим, у меня есть две темы, thread1 а также thread2:

на thread1

void process() {
while(true){
while (objectToProcess == NULL) {
boost::unique_lock lock(mutex);
waitingVariable.wait(lock);
}

doSomething(objToProcess);

objToProcess = NULL;
waitingVariable.notify();
}
}

на thread2:

void feedProcessor() {
while(true) {
while (objectToProcess != NULL) {
boost::unique_lock lock(mutex);
waitingVariable.wait(lock);
}

objToProcess = createNewObjectToProcess();
waitingVariable.notify();
}
}

В этом случае я считаю расточительным создавать новые unique_lock объекты каждый раз, когда мне нужно позвонить wait() метод условной переменной. Не могли бы вы рассказать мне о назначении таких объектов и о том, вносят ли они значительные накладные расходы?

Спасибо!

(Я вижу, что мой вопрос совпадает с этот вопрос, но мое беспокойство больше связано с накладными расходами, чем с целью …)

3

Решение

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

В оптимизированной сборке, скорее всего, нет необходимости использовать объект сложения вместо ручной блокировки мьютекса (и не забудьте сделать это, а также правильно разблокировать его при необходимости).

1

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

Идея условной переменной заключается в следующем:

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

При таком понимании ваш код должен измениться на следующее, чтобы защитить вашу обработку объекта:

boost::unique_lock lock(mutex);
while (objectToProcess == NULL) {

waitingVariable.wait(lock);
}

увидеть http://www.boost.org/doc/libs/1_55_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref

0