Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread Safety of datatstructures, Where to add synchronization primitives?

This is a design question that has been bugging me for a while now. It is pretty simple really, when you provide datastructure libraries do you build in the thread-safety primitives or just provide the constructs and let the system using it decide on how to implement the actual operations.

A quick example, a Circular buffer which supports a Producer, Consumer model. 2 Methods, Get and Write, each updates a global variable fill count. Now, do you just provide the mutexes to lock and let the code using the buffer grab the mutexes OR do you the locking internally and provide mutual exclusion out of the box.

STL seems to take the approach of doing it externally, but there are performance reasons of why you would want to provide finer grained locking.

Thoughts ?

like image 254
creatiwit Avatar asked Feb 03 '12 16:02

creatiwit


2 Answers

IMHO there is no clear winner to this discussions. There are pros and cons on either side of the board:

Having synchronization as a part of the API (inside the module):

  • Ensures that the caller won't have to spend too much time thinking about synchronization
  • Ensures caller won't make a mistake synchronizing (as it can be quite error prone to synchronize in languages that don't have in-built support for synchronization constructs)
  • You can do finer grained locking and optimize your library

Letting the caller synchronize

  • Gives the caller more control
  • In a single-threaded program the caller does not spend the time locking/unlocking

You could make a decision based on the case:

  • If it is a library that would most probably be used in a multi-threaded situation then provide in-built locking
  • If locking is going to be very tedious to implement (like a per node locking for a threadsafe queue) then provide it as a part of the library
  • Consider providing 2 versions of your library - locked and unlocked. Use templates in C++ to provide that with a nice syntax coupled with concurrent patterns such as ThreadSafe Interface
  • Be consistent! If you are providing a set of modules in a library make sure you are consistent in your syntax for threadsafe vs. non-threadsafe modules. This is my peeve with Java Swing that they are not consistent. Certain parts of the library are threadsafe while others aren't.

Hope this helps!

like image 85
Sid Avatar answered Oct 04 '22 16:10

Sid


I was thinking about the exact problem sometime ago. So I went ahead and wrote some sample code to understand the advantages and disadvantages of various approaches. So, instead of giving a theoretical answer, let me give you some code for the same problem that you have mentioned in the OP i.e. circular buffer (queue) with multiple producer and consumer.

Here it is.

Perhaps looking at the code may give you some clarification. I shall add more points if need be.. but for now, look at the code and derive the obvious!

like image 44
Sangeeth Saravanaraj Avatar answered Oct 04 '22 14:10

Sangeeth Saravanaraj