C++11 эквивалент для повышения shared_mutex

Есть ли C++11 эквивалент для boost::shared_mutex, Или другое решение для обработки ситуации с несколькими читателями / писателями в C++11?

3 ответа

Решение

Я пытался, но не смог получить shared_mutex в C++11. Это было предложено для будущего стандарта. Предложение здесь.

Изменить: пересмотренная версия (N3659) была принята для C++14.

Вот реализация:

http://howardhinnant.github.io/shared_mutex

http://howardhinnant.github.io/shared_mutex.cpp

Просто... Там нет ни одного. Не существует стандартной реализации C++ блокировки чтения-записи.

Но у вас есть несколько вариантов здесь.

  1. Вы оставлены на своих собственных устройствах, чтобы сделать свою собственную блокировку чтения-записи.
  2. Используйте реализацию для конкретной платформы, такую ​​как Win32, POSIX или Boost, как вы упомянули.
  3. Не используйте его вообще - используйте мьютекс, который уже существует в C++11.

Переход на #1 и реализация вашего собственного - страшное занятие, и вы можете озадачить ваш код условиями гонки, если вы не поняли его правильно. Существует эталонная реализация, которая может немного облегчить работу.

Если вы хотите независимый от платформы код или не хотите включать в свой код какие-либо дополнительные библиотеки для чего-то столь же простого, как блокировка чтения-записи, вы можете выбросить № 2 в окно.

И, # 3 имеет пару предостережений, которые большинство людей не осознают: использование блокировки чтения-записи часто менее производительно и имеет более сложный для понимания код, чем эквивалентная реализация, использующая простой мьютекс. Это связано с дополнительным ведением бухгалтерского учета, которое должно происходить за кулисами реализации блокировки чтения-записи.


Я могу только представить вам ваши варианты, на самом деле вы сами должны взвесить затраты и выгоды каждого из них и выбрать наиболее подходящий.


Изменить: C++ 17 теперь имеет shared_mutex тип для ситуаций, когда преимущества наличия нескольких одновременных считывателей перевешивают стоимость производительности shared_mutex сам.

Нет, для boost::shared_mutex в C++11.

Блокировки чтения / записи поддерживаются в C++14 или более поздней версии, хотя:

  • C++14 добавлено std::shared_timed_mutex
  • C++17 добавлено std::shared_mutex

Разница в том, что std::shared_timed_mutex добавляет дополнительные временные операции. Он реализует концепцию SharedTimedMutex, которая является расширением более простой концепции TimedMutex, реализованной std::shared_mutex,


Имейте в виду, что получение блокировки мьютекса для чтения / записи обходится дороже, чем приобретение обычного std::mutex, Как следствие, мьютекс чтения / записи не улучшит производительность, если у вас частые, но короткие операции чтения. Это лучше подходит для сценариев, в которых операции чтения являются частыми и дорогими. Цитировать из сообщения Энтони Уильямса:

Стоимость блокировки shared_mutex выше, чем блокировка простого std::mutex, даже для потоков чтения. Это необходимая часть функциональности - существует больше возможных состояний shared_mutex, чем мьютекса, и код должен обрабатывать их правильно. Эта стоимость зависит как от размера объекта (который как в вашей реализации, так и в моей реализации POSIX включает как простой мьютекс, так и от переменной условия), а также от выполнения операций блокировки и разблокировки.

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

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

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

Если операции чтения отнимают много времени, то последствия этого конфликта менее заметны, так как он затмевается временем, затраченным на удержание блокировки чтения. Тем не менее, выполнение трудоемких операций при удерживании замка является запахом конструкции.

Я думаю, что в подавляющем большинстве случаев есть лучшие альтернативы shared_mutex. Это может быть простой мьютекс, атомарная поддержка shared_ptr, использование тщательно сконструированного параллельного контейнера или что-то еще, в зависимости от контекста.

Другие вопросы по тегам