views:

93

answers:

3

Hi,

I'm looking for some advice on the best approach to synchronising access to properties of an object in C++. The application has an internal cache of objects which have 10 properties. These objects are to be requested in sets which can then have their properties modified and be re-saved. They can be accessed by 2-4 threads at any given time but access is not intense so my options are:

  1. Lock the property accessors for each object using a critical section. This means lots of critical sections - one for each object.

  2. Return copies of the objects when requested and have an update function which locks a single critical section to update the object properties when appropriate.

I think option 2 seems the most efficient but I just want to see if I'm missing a hidden 3rd option which would be more appropriate.

Thanks, J

A: 

You don't want critical sections, you want a mutex.

It's perfectly reasonable to have a single mutex for each object. Lock the mutex before ever reading or writing any of the properties, then unlock it quickly when done.

Mutexes have pretty low overhead when there's no contention. When there's lots of contention, they can definitely slow your program down.

dmazzoni
Why a mutex and not a critical section?
anon
that way 2 different threads cannot update 2 different properties of the same object.
Nick D
Errm... you want a mutex that can definitely slow your program?@Nick D: That way is which?
AOI Karasu
@AOI Karasu, using a mutex to lock the whole object.
Nick D
I believe that mutexes are less efficient than critical sections if we only need to synchronise within our application threads, there's no need to be going down to the kernel level for a mutex when a critical section would be sufficient.
+1  A: 

Firstly, I think you are worrying about the wrong thing. How do you know locking or copying causes bottlenecks in your code? Critical sections are fairly lightweight and don't cause much overhead, or, at least, not as much as you think. Just use the most lightweight locking primitive available. If you anticipate your system to be run on multi-processor hardware, you can even use a spinlock.

Secondly, do worry about simplicity of your concurrency model, before performance (hint: simpler model is easier to understand, to get right and to optimize). So if you can afford it, take copies of objects, this will ease the pain of dealing with TOCTOU race conditions in case you are doing complex transformations on the object set that depend on a number of previous values.

Alex B
A: 

Depending on how long it take to read a property from an object (I'm guessing it should be fairly trivial, like reading an int or std::string), you could use spin-locks as #3. They are the fastest way to synchronize threads. And maybe option #4, valid only for ints, is to do no locking at all and use only atomic operations. Maybe, the most efficiente solution, would be using atomics for all ints, per-property spin-locks for simple types (PODs and simple objects like std::string) and per-object mutexes/CS for anything more complex.

Only a profiler will be able to tell you which is the best option.

Gianni