об условной переменной в C ++ - PullRequest
2 голосов
/ 01 августа 2011

Я просматриваю переменную условия в следующей папке

http://software.intel.com/en-us/blogs/2010/10/01/condition-variable-support-in-intel-threading-building-blocks/

Here we have following code as example

#include "tbb/compat/condition_variable"  
using namespace std;
condition_variable my_condition;
tbb::mutex my_mtx;
bool present = false;

void producer() {
        unique_lock<tbb::mutex> ul( my_mtx );
        present = true;
        my_condition.notify_one();
}

void consumer() {
        while( !present ) {
            unique_lock<tbb::mutex> ul( my_mtx );
            my_condition.wait( ul );
        }
}

Насколько я понимаю, мы используем условную переменную для ожидания события.У меня есть следующие вопросы

  1. Почему мы используем мьютекс здесь, когда мы используем условную переменную?
  2. В функции customer () в цикле while мы берем мьютекс и ожидаем условие, какМожет ли функция производителя заблокировать мьютекс, если потребитель уже забрал его, и как он может уведомить об этом, не делает ли это тупик?
  3. Чем unique_lock отличается от scoped_lock?

Спасибо за вашу помощьв разъяснении моих вопросов.

Ответы [ 4 ]

3 голосов
/ 01 августа 2011

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

Основы условной переменной требуют блокировки для корректной работы.
Только поток с блокировкой должен пытаться изменить состояние переменной условия (т. Е. Путем вызова одной из функций переменной условия (это также защищает объект, над которым вы действительно работаете)).

В функции customer () в цикле while мы берем мьютекс и ожидаем условия, как функция-производитель может заблокировать мьютекс, если потребитель уже взял его

Когда вы вызываете wait () для условной переменной, поток переводится в спящий режим, а мьютекс освобождается. Когда поток проснулся, он должен повторно получить блокировку, прежде чем функция wait () вернется к пользовательскому коду.

и как он может сообщить, что не тупик?

Он не блокируется, потому что wait () снимает блокировку перед переводом потока в спящий режим.

Чем unique_lock отличается от scoped_lock?

В этом контексте нет. Но если у вас есть какая-либо конкретная реализация, укажите ее реализацию, и мы можем обсудить ее более подробно.

1 голос
/ 01 августа 2011

Должно быть (для ясности):

void producer() {
        unique_lock<tbb::mutex> ul( my_mtx ); // protect present
        present = true;
        my_condition.notify_one();
}

void consumer() {
        unique_lock<tbb::mutex> ul( my_mtx );   // protect preset
        while( !present ) {
            my_condition.wait( ul );
        }
}

От: http://www.boost.org/doc/libs/1_46_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref.condition_variable.wait что очень похоже.

void wait (boost :: unique_lock & lock)

Предпосылка: Блокировка заблокирована текущим потоком, и ни один другой поток в настоящее время ожидает * this или выполнение члена mutex () функция блокировки объектов, представленных в вызовах для ожидания или timed_wait во всех потоках, ожидающих в данный момент * это вернет то же значение, что и lock-> mutex () для ожидания этого вызова.

Эффекты: Атомно вызовите lock.unlock () и блокирует текущий поток. поток разблокируется, когда получено уведомление об этом this-> notify_one () или this-> notify_all (), или с явной стороны. Когда нить разблокирована (для по какой-либо причине), блокировка восстанавливается путем вызова lock.lock () перед вызовом ожидания возвращается. Замок также повторно приобретен вызывая lock.lock (), если функция завершается с исключением.

Постусловие: Блокировка заблокирована текущим потоком.

0 голосов
/ 01 августа 2011
  1. Мьютекс используется для защиты переменной условия
  2. мьютекс разблокируется автоматически, когда вы вызываете my_condition.wait (), а когда возвращается my_conditioin.wait (), он разблокирует мьютекс, после чего вы можете проверить условие в while (! Present). То есть, если wait () не может заблокировать мьютекс, потому что другой поток работает быстрее, он будет заблокирован. Как только более быстрый поток завершается, функция wait () возвращается с заблокированным мьютексом, но условие может стать ложным, а затем поток снова ждет. Таким образом, мьютекс используется для защиты состояния, которое возможно, как сказано в первом ответе.
0 голосов
/ 01 августа 2011

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

...