1

I have a problem with using std:map in my multithread application. I need to lock the map object when thread is writing to this object. Parallely another threads which reading this object should shop until writing process is finish.

Sample code:

std::map<int, int> ClientTable;

int write_function() //<-- only one thread uses this function
{
  while(true)
  {
    //lock ClientTable
    ClientTable.insert(std::pair<int, int>(1, 2)); // random values
    //unlock ClientTable

    //thread sleeps for 2 secs
  }
}

int read_function()  //<--- many thread uses this function
{
  while(true)
  {
     int test = ClientTable[2]; // just for test
  }
}

How to lock this std::map object and correctly synchronise this threads?

Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
Robert
  • 507
  • 2
  • 9
  • 20
  • 1
    You probably want to change `read_function` to use `map`'s `find` member function instead of `operator[]`, as the latter can actually modify the `map`. Usually that's a mild annoyance (at worst) but in this case, becomes much more serious. – Jerry Coffin Jul 08 '12 at 14:06

2 Answers2

2

Looks like what you need is a typical read-write lock, allowing any number of readers but a single writer. You can have a look at boost's shared_mutex.

Additional usage examples can be found here: Example for boost shared_mutex (multiple reads/one write)?

Community
  • 1
  • 1
Tudor
  • 61,523
  • 12
  • 102
  • 142
  • map is thread safe for only reading operations, i need to lock all other writers and readers when writer is working. When readers working no lock needed. How can i use shared_mutex for it? I dont know anything about it(. Thanks! – Robert Jul 08 '12 at 13:59
  • @Robert: This lock does exactly that: when a thread wants to acquire the write lock all other threads are locked-out, but when a thread wants to read any other thread can read at the same time (unless someone is writing, like I said). Check the examples in the question I linked for how to use it. – Tudor Jul 08 '12 at 14:02
  • As ChristianStieber suggests, `read_function` is a misleading name, because `std::map`'s `operator[]` can (will) actually modify the map, inserting the item with the specified key if it isn't already present. – Jerry Coffin Jul 08 '12 at 14:03
0

Well, since a std::map doesn't have a builtin lock, you would have to use a separate lock that protects the map. If the map is all that's protected by that lock you could subclass map to add the lock there along with "lock" and "unlock" calls, but if the lock will be used for other items as well then it's probably not the best idea to do that.

As for "how to correctly synchronize" -- that's very specific to the application at hand. However, for the example given, you have to insert the lock/unlock calls around the read operation as well.

If you have read/write locks, this might also be a good application for one of these.

Christian Stieber
  • 9,954
  • 24
  • 23
  • 1
    If the lock protects the map and other related objects, it's probably a good idea to bundle the map, the lock, and those other related objects into a class. That class can offer a function that calls the map's `insert` function while holding the lock. Ditto for `operator[]` (returning a non-reference rvalue, of course). – David Schwartz Jul 08 '12 at 12:56