Отложенные блокировки и `boost::lock`

Я читал о разнице между lock_guard и unique_lock и обнаружил, что unique_lock — это расширенная версия lock_guard. Таким образом, с уникальной блокировкой блокировку всегда можно отложить. Я читал это статью и наткнулся на boost::lock. Я хотел знать, как я могу использовать этот метод. Я пробовал следующее:

boost::mutex mutx;
boost::unique_lock<boost::mutex> guard (mutx,boost::defer_lock);
boost::lock(guard); //too few arguments in function call.

Я был бы признателен, если бы кто-нибудь объяснил мне, что делает boost::lock и как это работает. Спасибо.


person Rajeshwar    schedule 31.10.2013    source источник


Ответы (2)


Целью boost::lock является блокировка нескольких блокировок, гарантирующая отсутствие взаимной блокировки.

Рассмотрим случай:

unique_lock<...> a, b;

// thread 1
a.lock();
b.lock();
...

// thread 2
b.lock();
a.lock();

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

boost::lock избегает этой проблемы, разблокируя все замки, которые он уже заблокировал, когда сталкивается с заблокированным замком. Реализация для случая с двумя замками может выглядеть примерно так:

template<class L1, class L2>
void lock(L1& l1, L2& l2) 
{
    while (1) {
        if (l1.try_lock()) {
            if (l2.try_lock()) {
                return;
            } else {
                l1.unlock();
            }
        } 
        // yield (execute another thread) here
    }
}
person user12    schedule 31.10.2013

Вы имеете в виду

mutex mutx
unique_lock<mutex> guard(mutx,defer_lock);
guard.lock();

?

Как только у вас есть lock_guard или unique_lock, вы перестаете напрямую возиться с мьютексом и работаете с охранным объектом.

person DanielKO    schedule 31.10.2013