Hacker News

Понимание Std:Shared_mutex из C++17

Узнайте, как std::shared_mutex из C++17 обеспечивает эффективную блокировку чтения и записи, позволяя выполнять несколько одновременных операций чтения, обеспечивая при этом монопольный доступ для записи.

2 минута чтения

Mewayz Team

Editorial Team

Hacker News

Понимание std::shared_mutex из C++17

std::shared_mutex, представленный в C++17, представляет собой примитив синхронизации, который позволяет нескольким потокам одновременно удерживать общие блокировки (чтение), обеспечивая при этом монопольный доступ для операций записи. Он решает одну из наиболее распространенных проблем параллелизма в современном C++, предоставляя разработчикам чистый стандартный способ реализации блокировки чтения-записи без обращения к сторонним библиотекам или API-интерфейсам для конкретной платформы.

Что такое std::shared_mutex и почему он был добавлен в C++17?

До C++17 разработчикам, которым требовалась семантика чтения и записи, приходилось полагаться на специфичные для платформы решения, такие как pthread_rwlock_t в системах POSIX или SRWLOCK в Windows, или они использовали сторонние библиотеки, такие как Boost. Комитет по стандартизации C++17 признал этот пробел и добавил std::shared_mutex в заголовок , чтобы напрямую устранить его.

Основная идея проста: во многих реальных программах данные читаются гораздо чаще, чем записываются. Стандартный std::mutex сериализует весь доступ, включая чтение, что создает ненужные узкие места. std::shared_mutex снимает это ограничение, различая два режима блокировки:

Общая блокировка (чтение) — получена с помощью lock_shared(); несколько потоков могут хранить это одновременно, что делает его идеальным для одновременного чтения.

Эксклюзивная блокировка (запись) — получена с помощью lock(); одновременно его может удерживать только один поток, и пока он удерживается, общие блокировки не допускаются.

std::shared_lock — оболочка RAII, которая вызывает lock_shared() при создании и unlock_shared() при уничтожении, предотвращая утечку ресурсов.

std::unique_lock / std::lock_guard — используется в эксклюзивном режиме, обеспечивая полную защиту операций записи и безопасность исключений.

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

Как использовать std::shared_mutex в реальном коде с комментариями?

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

#include <общий_мьютекс>

#include <неупорядоченная_карта>

#include <строка>

класс ConfigRegistry {

изменяемый std::shared_mutex mtx_; // защищает карту ниже

std::unordered_map data_;

💡 DID YOU KNOW?

Mewayz replaces 8+ business tools in one platform

CRM · Invoicing · HR · Projects · Booking · eCommerce · POS · Analytics. Free forever plan available.

Начать бесплатно →

публика:

// Путь чтения: несколько потоков могут вызывать это одновременно

std::string get(const std::string& key) const {

std::shared_lock lock(mtx_); // общая блокировка — безопасна для одновременного чтения

авто это = data_.find (ключ);

верните его!= data_.end() ? это->секунда: "";

}

// Путь записи: требуется монопольный доступ

void set(const std::string& key, const std::string& val) {

std::unique_lock lock(mtx_); // эксклюзивная блокировка — блокирует всех читателей

data_[ключ] = значение;

}

};

Обратите внимание, что комментарии объясняют цель каждого выбора блокировки, а не просто повторяют, что делает код. Это золотой стандарт: комментарии должны отвечать почему, а не что. Ключевое слово mutable во мьютексе позволяет объявить get() const, сохраняя при этом возможность блокировки, что является распространенным идиоматическим шаблоном.

Ключевая информация: всегда используйте оболочки блокировки RAII (std::shared_lock, std::unique_lock) с std::shared_mutex — никогда не вызывайте lock() и unlock() вручную. Ручная блокировка при наличии исключений — это гарантированный путь к взаимоблокировкам и неопределенному поведению.

Каковы распространенные ошибки при работе с std::shared_mutex?

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

All Your Business Tools in One Place

Stop juggling multiple apps. Mewayz combines 207 tools for just $19/month — from inventory to HR, booking to analytics. No credit card required to start.

Try Mewayz Free →

Try Mewayz Free

All-in-one platform for CRM, invoicing, projects, HR & more. No credit card required.

Start managing your business smarter today

Join 30,000+ businesses. Free forever plan · No credit card required.

Нашли это полезным? Поделиться.

Ready to put this into practice?

Join 30,000+ businesses using Mewayz. Free forever plan — no credit card required.

Начать бесплатный пробный период →

Готовы действовать?

Начните ваш бесплатный пробный период Mewayz сегодня

Бизнес-платформа все-в-одном. Кредитная карта не требуется.

Начать бесплатно →

14-day free trial · No credit card · Cancel anytime