Есть ли какое-либо идиоматическое явное использование mutex :: lock () или unlock ()?

Рекомендуемый способ использовать mutex для блокировки критической области кода - через RAII, т.е.

mutex_type mutex;
{ // start of critical region
  std::lock_guard<mutex_type> lock(mutex);   // first statement in critical region
  // ... do critical stuff, may throw an exception
} // end of critical region

, чтобы при возникновении исключения в критической области мьютекс по-прежнему разблокировался (деструктором std::lock_guard). Тем не менее, таким образом члены mutex::lock() и mutex::unlock() никогда не вызывается явно кодом пользователя.

Q Что, если таковое имеется, является основным идиоматическим явным использованием mutex::lock()?

Я спрашиваю, иначе нет никакого смысла в mutex::lock() публичном члене, продвигающем плохой код (который избегает std::lock_guard)

Edit Поскольку и std::lock_guard<>, и std::mutex определены в тот же заголовок, std::mutex может легко подружиться std::lock_guard<std::mutex и имеют методы lock() и unlock() защищенный:

class mutex      // use only with lock_guard<mutex>
{
  friend class lock_guard<mutex>;         // support acquire-release semantic via RAII
  friend class scoped_lock_guard<mutex>;  // for supporting more complicated semantic,
                                          //     possibly remembering the mutex state.
  // ...
protected:
  void lock();
  bool try_lock();
  void unlock();       
};

class raw_mutex  // use if you absolutely must explicitly lock, try_lock, or unlock
: public mutex
{
public:
  using mutex::lock;
  using mutex::try_lock;
  using mutex::unlock;
};

Аргумент в ответ на мой вопрос заключается в том, что единственным безопасным для исключения способом использования mutex::lock() является через RAII. Таким образом, единственное разумное явное использование должно включать только методы noexcept между вызовами lock (или try_lock) и unlock. Однако, так как noexcept является только наводящим и не обещающим, такое использование будет небезопасным. Q правильно?

4 голоса | спросил Walter 5 AMpSat, 05 Apr 2014 01:11:38 +040011Saturday 2014, 01:11:38

2 ответа


0

lock_guard - не единственное, что нужно вызвать lock /unlock в mutex. unique_lock, lock, try_lock и condition_variable_any также должны работать с мьютексами. И это только стандартные типы. Дружба в этом случае создает тесную связь, которая становится помехой.

ответил Nevin 6 AMpSun, 06 Apr 2014 06:53:58 +040053Sunday 2014, 06:53:58
0

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

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

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

Ваша программа контролирует два ресурса, она должна читать и выполнять последовательность команд. Возможные команды:

  • заблокировать ресурс # 1: 1>
  • заблокировать ресурс № 2: 2>
  • разблокировать ресурс № 1: 1<
  • ресурс разблокировки № 2: 2<
  • записать x на ресурс № 1: 1x
  • записать x на ресурс №2: 2x

ваша программа может ожидать ввода, например 1> 1a 2> 2b 1c 1< 2d 2<, что делает невозможным использование статических областей для RAII, если программа подчиняется командам (области должны частично перекрываться). Поэтому я думаю, что это иллюстрирует одну ситуацию, когда необходима явная блокировка /разблокировка.


Существует по крайней мере еще один возможный сценарий, который исходит из того факта, что взаимное исключение - не единственная ситуация, когда можно использовать mutex: его можно использовать и для синхронизации.

Рассмотрим два параллельных процесса: P и Q, каждый с обозначенной точкой в ​​своем коде. Мы требуем, чтобы Q не смог пройти через обозначенную точку до P достигает своего. Это требование можно выполнить, используя mutex, инициализированный как locked состояние и размещение операции lock() прямо перед обозначенной точкой Q и unlock() сразу после обозначенной точки P. Можно легко проверить, что эта установка решает проблему.

Здесь lock() помещается в один процесс и unlock() в другом, опять же, очевидно, нет статической области видимости, которая может их заключить, поэтому нам нужно, чтобы оба были доступны независимо друг от друга.

ответил xxa 15 AMpTue, 15 Apr 2014 02:06:05 +040006Tuesday 2014, 02:06:05

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132