views:

141

answers:

4

Hi all,

I received a code that is not for multi-threaded app, now I have to modify the code to support for multi-threaded.

I have a Singleton class(MyCenterSigltonClass) that based on instruction in: http://en.wikipedia.org/wiki/Singleton_pattern I made it thread-safe

Now I see inside the class that contains 10-12 members, some with getter/setter methods. Some members are declared as static and are class pointer like:

static Class_A*    f_static_member_a;
static Class_B*    f_static_member_b;

for these members, I defined a mutex(like mutex_a) INSIDE the class(Class_A) , I didn't add the mutex directly in my MyCenterSigltonClass, the reason is they are one to one association with my MyCenterSigltonClass, I think I have option to define mutex in the class(MyCenterSigltonClass) or (Class_A) for f_static_member_a.

1) Am I right?

Also, my Singleton class(MyCenterSigltonClass) contains some other members like

Class_C  f_classC;

for these kind of member variables, should I define a mutex for each of them in MyCenterSigltonClass to make them thread-safe? what would be a good way to handle these cases?

Appreciate for any suggestion.

-Nima

A: 

If this is the first time you're doing threading, consider not accessing the singleton from the background thread. You can get it right, but you probably won't get it right the first time.

Realize that if your singleton exposes pointers to other objects, these should be made thread safe as well.

jdv
A: 

You don't have to define a mutex for each member. For example, you could instead use a single mutex to synchronize access each to member, e.g.:

class foo
{
public:
  ...
  void some_op()
  {
    // acquire "lock_" and release using RAII ...
    Lock(lock_);
    a++;
  }

  void set_b(bar * b)
  {
    // acquire "lock_" and release using RAII ...
    Lock(lock_);
    b_ = b;
  }

private:

  int a_;
  bar * b_;

  mutex lock_;
}

Of course a "one lock" solution may be not suitable in your case. That's up to you to decide. Regardless, simply introducing locks doesn't make the code thread-safe. You have to use them in the right place in the right way to avoid race conditions, deadlocks, etc. There are lots of concurrency issues you could run in to.

Furthermore you don't always need mutexes, or other threading mechanisms like TSS, to make code thread-safe. For example, the following function "func" is thread-safe:

class Foo;
void func (Foo & f)
{
  f.some_op();  // Foo::some_op() of course needs to be thread-safe.
}

// Thread 1
Foo a;
func(&a);

// Thread 2
Foo b;
func(&b);

While the func function above is thread-safe the operations it invokes may not be thread-safe. The point is you don't always need to pepper your code with mutexes and other threading mechanisms to make the code thread safe. Sometimes restructuring the code is sufficient.

There's a lot of literature on multithreaded programming. It's definitely not easy to get right so take your time in understanding the nuances, and take advantage of existing frameworks like Boost.Thread to mitigate some of the inherent and accidental complexities that exist in the lower-level multithreading APIs.

Void
A: 

I'd really recommend the Interlocked.... Methods to increment, decrement and CompareAndSwap values when using code that needs to be multi-thread-aware. I don't have 1st-hand C++ experience but a quick search for http://www.bing.com/search?q=c%2B%2B+interlocked reveals lots of confirming advice. If you need perf, these will likely be faster than locking.

No Refunds No Returns
As far as I research on Web, the Interlocked is support on Windows platform, I use m Mac OS X, do you think it would be a limit for me?
Nima
+1  A: 
Neal S.
Thanks a lot. It was great help.
Nima