C++ Thread-Safe Map

2020-01-28 08:01发布

Does anyone know where I can find an implimentation that wraps a std::map and makes it thread safe? When I say thread safe I mean that it offers only serial access to the map, one thread at a time. Optimally, this map should use only the standard-library and / or boost constructs.

8条回答
男人必须洒脱
2楼-- · 2020-01-28 08:28
成全新的幸福
3楼-- · 2020-01-28 08:29

This is up to the application to implement. A "thread-safe" map would make individual calls into the map thread-safe, but many operations need to be made thread-safe across calls. The application that uses the map should associate a mutex with the map, and use that mutex to coordinate accesses to it.

Trying to make thread-safe containers was a mistake in Java, and it would be a mistake in C++.

查看更多
看我几分像从前
4楼-- · 2020-01-28 08:30

There is a proposition here (by me - shameless plug) that wraps objects (including STL containers) for efficient (zero-cost) thread safe access:

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

The basic idea is very simple. There are just a few wrapper classes used to enforce read/write locking and, at the same time, presenting either a const (for read-only) or non-const (for read-write) view of the wrapped object.

The idea is to make it compile-time impossible to improperly access a resource shared between threads.

Implementation code can be found here:

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

查看更多
再贱就再见
5楼-- · 2020-01-28 08:37

Does not meet the criteria that you have specified, but you could have a look at the TBB containers. There is so called concurrent_hash_map which allows multiple threads to access concurrently the data in the map. There are some details, but everything is nicely documented and can give you an idea of the "concurrent container". Depending on your needs this might be totally inappropriate...

查看更多
聊天终结者
6楼-- · 2020-01-28 08:48

Try this library

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

It is implemented in a modern c++ policy based approach.

Here is some cut from the link to show the idea with the 'vector' case

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.
}
查看更多
再贱就再见
7楼-- · 2020-01-28 08:48

I came up with this (which I'm sure can be improved to take more than two arguments):

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

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

This allows you to do:

// 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";
}

If you wish to use an std::recursive_mutex and an std::set, that would also work.

查看更多
登录 后发表回答