Потокобезопасная Карта C++

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

8 ответов


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


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


boost shared_mutex обеспечит лучший подход с несколькими читателями / одним писателем для упаковки стандартной карты с учетом ваших ограничений. Я не знаю никаких "предварительно построенных" реализаций, которые сочетают эти два, так как задача обычно тривиальна.


Это зависит от приложения для реализации. "Потокобезопасная" карта будет делать отдельные вызовы в потокобезопасную карту, но многие операции должны быть сделаны потокобезопасными на звонки. Приложение, использующее карту, должно связать мьютекс с картой и использовать этот мьютекс для координации доступа к ней.

попытка сделать потокобезопасные контейнеры была ошибкой в Java, и это было бы ошибкой в C++.



попробуйте эту библиотеку

http://www.codeproject.com/KB/threads/lwsync.aspx

он реализован в современном подходе на основе политики c++.

вот некоторые вырезанные из ссылки, чтобы показать идею с "векторным" случаем

typedef lwsync::critical_resource<std::vector<int> > sync_vector_t;
sync_vector_t vec;

// some thread:
{
   // Critical resource can be naturally used with STL containers.
   sync_vector_t::const_accessor vec_access = vec.const_access();
   for(std::vector<int>::const_iterator where = vec_access->begin();
         where != vec_access->end();
         ++where;
        )
   std::cout << *where << std::endl;
}

sync_vector_t::accessor some_vector_action()
{
   sync_vector_t::accessor vec_access = vec.access();
   vec_access->push_back(10);
   return vec_access;
   // Access is escalated from within a some_vector_action() scope
   // So that one can make some other action with vector before it becomes
   // unlocked.
}

{
   sync_vector_t::accessor vec_access = some_vector_action();
   vec_access->push_back(20);
   // Elements 10 and 20 will be placed in vector sequentially.
   // Any other action with vector cannot be processed between those two
   // push_back's.
}

Я придумал это (что, я уверен, можно улучшить, чтобы взять более двух аргументов):

template<class T1, class T2>
class combine : public T1, public T2
{
public:

    /// We always need a virtual destructor.
    virtual ~combine() { }
};

Это позволяет делать:

// Combine an std::mutex and std::map<std::string, std::string> into
// a single instance.
combine<std::mutex, std::map<std::string, std::string>> lockableMap;

// Lock the map within scope to modify the map in a thread-safe way.
{
    // Lock the map.
    std::lock_guard<std::mutex> locked(lockableMap);

    // Modify the map.
    lockableMap["Person 1"] = "Jack";
    lockableMap["Person 2"] = "Jill";
}

Если вы хотите использовать std:: recursive_mutex и std:: set, это также будет работать.


здесь есть предложение (мной-бесстыдная вилка), которое обертывает объекты (включая STL контейнеры) для эффективного (нул-цены) потока безопасный доступ:

https://github.com/isocpp/CppCoreGuidelines/issues/924

основная идея очень проста. Существует всего несколько классов-оболочек, используемых для принудительной блокировки чтения / записи и, в то же время, представления const (только для чтения) или non-const (для чтения-записи объект.

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

код реализации можно найти здесь:

https://github.com/galik/GSL/blob/lockable-objects/include/gsl/gsl_lockable