В чем разница между «мьютексом» и «замком»? - PullRequest
22 голосов
/ 21 февраля 2012

Я очень озадачен разницей между замком и мьютексом.В документах Boost говорится:

Типы блокировок

  • Шаблон класса lock_guard
  • Шаблон класса unique_lock
  • Шаблон классаshared_lock
  • шаблон класса upgrade_lock
  • шаблон класса upgrade_to_unique_lock
  • Mutex-специфичный класс scoped_try_lock

Mutex Types

  • Класс mutex
  • Typedef try_mutex
  • Класс timed_mutex
  • Класс recursive_mutex
  • Typedef recursive_try_mutex
  • Класс recursive_timed_mute*
  • Класс shared_mutex

В другой статье я вижу такие функции:

boost::shared_mutex _access;
void reader()
{
  boost::shared_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access
}    
void conditional_writer()
{
  boost::upgrade_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access

  if (something) {
    boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
    // do work here, but now you have exclusive access
  }
  // do more work here, without anyone having exclusive access
}

Обновлены вопросы

  1. Кто-нибудь может предложить какое-нибудь разъяснение между "mutex" и "lock"?
  2. Необходимо ли создать shared_lock для shared_mutex ?Что произойдет, если я создам unique_lock для shared_mutex ?
  3. Или если я создаю shared_lock для мьютекса , значит ли это, что мьютекс не может быть общим для нескольких потоков?

Ответы [ 3 ]

39 голосов
/ 21 февраля 2012

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

A объект блокировки - это объект, который инкапсулирует эту блокировку. Когда объект построен, он получает блокировку на мьютексе. Когда он разрушен, замок снимается. Обычно вы создаете новый объект блокировки для каждого доступа к общим данным.

12 голосов
/ 21 февраля 2012

Мьютекс - это объект, который можно заблокировать. Замок - это объект, который поддерживает замок. Чтобы создать блокировку, вам нужно передать ей мьютекс.

1 голос
/ 10 июня 2015

Блокировки могут обеспечивать взаимное исключение, но не синхронизацию условий. В отличие от семафора, у блокировки есть владелец, и владение играет важную роль. роль в поведении замка

пример -

class lockableObject { public void F() {
mutex.lock(); ...; mutex.unlock();
}
public void G() {
mutex.lock(); ...; F(); ...; mutex.unlock();
}
private mutexLock mutex; }
// method G() calls method F()

Блокировка мьютекса в классе lockableObject используется для превращения методов F () и G () в критические секции. Таким образом, только один поток одновременно может выполняться внутри метода lockableObject. Когда поток вызывает метод G (), мьютекс блокируется. Когда метод G () вызывает метод F (), mutex.lock () выполняется в F (), но вызывающий поток не блокируется, поскольку он уже владеет мьютексом. Если бы мьютекс был двоичным семафором, а не блокировкой, вызов из G () в F () заблокировал бы вызывающий поток, когда mutex.P () был выполнен в F (). (Напомним, что завершение операций P () и V () на двоичном семафоре должно чередоваться.) Это создаст тупик, поскольку никакие другие потоки не смогут выполняться внутри F () или G ().

Это различия между замками и двоичными семафорами: 1 Для двоичного семафора, если два вызова сделаны toP () без какого-либо промежуточного вызова V (), второй вызов заблокируется. Но поток, который владеет блокировкой и снова запрашивает владение, не блокируется. (Остерегайтесь того факта, что блокировки не всегда рекурсивны, поэтому проверьте документацию перед использованием блокировки.) 2 Владелец для последовательных вызовов lock () и unlock () должен быть одним и тем же потоком. Но последовательные вызовы P () и V () могут выполняться разными потоками.

...