Подтвердить что ты не робот

Какая разница между "мьютексом" и "блокировкой"?

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

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

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

Типы Mutex

  • Мьютекс класса
  • Typedef try_mutex
  • Класс timed_mutex
  • Класс recursive_mutex
  • Typedef recursive_try_mutex
  • Класс recursive_timed_mutex
  • Класс 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
}

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

  • Может ли кто-нибудь предложить некоторые пояснения между "мьютексом" и "блокировкой"?
  • Необходимо ли создать shared_lock для shared_mutex? Что произойдет, если я создам unique_lock для shared_mutex?
  • Или, если я создаю shared_lock для мьютекса, означает ли это, что мьютекс может не разделяться между несколькими потоками?
4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

example -

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