В чем разница между" мьютексом "и"замком"?

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

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

  • шаблон класса lock_guard
  • шаблон класса unique_lock
  • шаблон класса shared_lock
  • класс шаблон upgrade_lock
  • шаблон класса upgrade_to_unique_lock
  • специфичный для мьютекса класс scoped_try_lock

мьютекс Типы

  • мьютекс класс
  • 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
}

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

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

3 ответов


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

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


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


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

пример

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 () блокировал бы вызывающий поток при мьютексе.P () было выполнено в F (). (Напомним, что сочетания операций P() и V() на двоичном семафоре должны чередоваться.) Это создаст тупик, так как никакие другие потоки не смогут выполняться внутри F() или G().

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