Synchronized methods Java-like: is there a way?


#1

Is there a way to get some component methods to be monitored like the synchronized methods in Java? I’m getting some strange behaviours due to “thread unsafe” calls.

How do I get my application to be more thread safe as easy as Java synchronized methods?


#2

In C++, you have the volatile keyword.

If you declare an object volatile, then the compiler will call the volatile methods of your object.

What you can do (this is what I do), is put a CriticalSection in your shared object, and write all the methods with and without “volatile” qualifier.
In the volatile version, I lock the section, call the non-volatile method, and release the section. That way, it’s synchronized. And better, it’s done at compile time (the compiler will refuse to call a non-volatile method for a volatile object)

BTW, this works only if the class where you use the object is declaring the object as volatile (i.e “volatile MySharedObject object;”)

Take care however that for plain old data (like int, float, etc…), the compiler don’t make a difference if they are volatile or not (as they don’t have methods), so be careful to protect them, or wrap them in classes.
On the other side, the POD can be atomically assigned, so you can optimize this a bit.

You should read: this article


#3

volatile is absolutely not equivalent to synchronized in java.
If you ensure thread safeness using volatile you’re totally lost.

Instead declare a CriticalSection in your object and use ScopedLock on it on each of your “synchronized” method

HTH


#4

Read the previous post entirely, then the article, and they react…


#5

Obvisouly the guy is a newb, so talking about volatile and its use for thread safety is imho a bad call.

my 2 cents.


#6

[quote=“otristan”]Obvisouly the guy is a newb, so talking about volatile and its use for thread safety is imho a bad call.

my 2 cents.[/quote]

Could you please explain why do you think it’s a bad thing, instead of calling him a newb? I don’t understand this topic that much myself, so I think constructive criticism would be appreciated…


#7

In java, you’ll code something like:

 class MySharedObject
 {
     public int myData;
     public void mySharedFunc(int o) synchronized
     {
         myData += o;
     }
     MySharedObject() { myData = 0; }
  };

  // In one thread, you'll do :
  MySharedObject obj = getMySharedObj();
  obj.mySharedFunc(3);

  // In the other thread, you'll do :
  MySharedObject obj = getMySharedObj();
  obj.mySharedFunc(2);

In Java, because of the “synchronized” keyword, you are sure that myData will be 5 after the 2 threads, because entering the mySharedFunc is done internally by locking MySharedObject’s mutex.

If you write this code in C++:

 class MySharedObject
 {
     public: int myData;
     void mySharedFunc(int o) 
     {
         myData += o;
     }
     MySharedObject() { myData = 0; }
  };

  // In one thread, you'll do :
  MySharedObject &obj = getMySharedObj();
  obj.mySharedFunc(3);

  // In the other thread, you'll do :
  MySharedObject &obj = getMySharedObj();
  obj.mySharedFunc(2);

You have no guarantee of the result of myData. If the first thread is stopped just after “load myData value in a register, add o value to the register”, then the 2nd thread execute entirely, the first thread finish “store the register back in myData” will result in myData being 3 not 5.

The gross solution is to lock a critical section while entering mySharedFunc(), and release it while leaving (so that the 2nd thread can’t execute until the first thread has finished)

However, if later on, you had other shared methods and forgot to lock the section, you’ll hardly understand the errors you’ll get.

The article above give a better solution which is:

 class MySharedObject
 {
     public: int myData;
     void mySharedFunc(int o) 
     {
         myData += o;
     }
     
     MySharedObject() { myData = 0; }
     
     // Multithreading access
     volatile Lock lock;
     void mySharedFunc(int o) volatile 
     { 
           lock.Acquire(); 
           const_cast<MySharedObject*>(this)->mySharedFunc(o); // Call the non-volatile version
           lock.Release();
      }
  };

  // In one thread, you'll do :
  volatile MySharedObject &obj = getMySharedObj();
  obj.mySharedFunc(3); // Will call the volatile version

  // In the other thread, you'll do :
  volatile MySharedObject &obj = getMySharedObj();
  obj.mySharedFunc(2); // Will call the volatile version

This improvement guarantee that if, later on, you add a method without making a volatile version of it, it won’t compile ( a volatile object calls its volatile methods)
This means that the multithreading code can be checked at compile-time for safety, not at jeopardize your run-time behavior.


#8

[quote=“yanco”][quote=“otristan”]Obvisouly the guy is a newb, so talking about volatile and its use for thread safety is imho a bad call.

my 2 cents.[/quote]

Could you please explain why do you think it’s a bad thing, instead of calling him a newb? I don’t understand this topic that much myself, so I think constructive criticism would be appreciated…[/quote]

I wasn t saying X-Ryl669 was a newb. I’m sure he’s very capable especially regarding the link he has given.
I was telling that br_programmer seemed beginner regarding threading issue, so suggesting him to ensure thread safety using techniques describes in the article is a little bit too complicated imho.


#9

Thanks, guys.

Can you have some example of using the class CriticalSection? I think this approach appears to be more straightforward.

[]s


#10

class A
{

void func()
{
ScopedLock lock(mLock);
// do some stuff
}

void func2()
{
ScopedLock lock(mLock);
// do some otherstuff
}

private:
CriticalSection mLock;
};


#11