CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Aug 2009
    Location
    Finally back in Alaska
    Posts
    141

    A few questions about thread safety

    Hello all,

    I have a library with a few classes in it that run great in a single threaded environment, but I am getting more and more into multithreaded apps and even though I havent had problems yet, would like to avoid them by implementing thread safety. I realize it probably would have been better in native c++, but chose to focus on managed c++ when I taught myself and will convert it when I start teaching myself native c++.

    Anyways, this was written in ms C++/cli 2008. All of the classes are immutable, once the object is created, it never changes that values. The assignment and math operators all create a new object and return that, however, I do not believe that it is thread safe in that if an instance is assigning itself to a new reference and another thread is reading (or worse assigning a different instance to it) the behavior would appear to be unpredictable. After reading quite a few articles on designing thread safety, I think I have an idea of how to approach it, but I do have a few questions to clear up first.

    For example, I know that static methods are shared between all instances, but, are any instance variables created within the method shared also are does each invocation have its own copy? for example:

    Code:
     
    
    static MiniBI^ ModPow(MiniBI^ _base, MiniBI^ _exponent, MiniBI^ _modulus){
    
           MiniBI^ _retval=gcnew MiniBI();    //would this variable be shared or would each invocation create its own instance?
    
            .......rest of algorithm
    
          return _retval;
    
    }
    Another question I have is about mutexes. If I create one mutex for the class and call WaitOne() when first entering the method would it allow the same thread to enter a different method within the same class? Example:

    Code:
     
    
    static MiniBI^ operator*(MiniBI^ _val1, MiniBI^ _val2){
    
         _mymutex->WaitOne();
    
         MiniBI^ _retval=gcnew MiniBI();
    
        .....//guts of method
    
         return _retval;
    
         _mymutex->ReleaseMutex();
    
    }
    static MiniBI^ Pow(MiniBI^ _base, MiniBI^ _exponent){
    
         _mymutex->WaitOne();
    
         MiniBI^ _retval=gcnew MiniBI();
    
         ........
    
          for(int x=0;x<_exponent->Length;x++){
    
                 _retval=_retval*_retval;   //if this thread is in this method, will the operator* let this thread in to do its work
    
                if(_exponent[x]==1){
    
                       _retval=_retval*_base;     ///same with this one
    
                }
    
           }
    
          return _retval;
    
          _mymutex->ReleaseMutex();
    
    }
    So would the operator* method let the thread through since it allready has control of the mutex in the Pow method? would it still let it through if another thread had allready called WaitOne() in the operator* before it?

    All of the operators are overloaded (and static) but, all of them convert the int to a MiniBI^ then call the version of the operator that handles only MiniBI^ values. Example:

    Code:
     
    
    static MiniBI^ operator+(MiniBI^ _val1, MiniBI^ _val2){
    
         _mymutex->WaitOne();
    
         MiniBI^ _retval=gcnew MiniBI();
    
         .....guts of routine
    
          return _retval;
    
         _mymutex->ReleaseMutex();
    
    }
    
    static MiniBI^ operator+(MiniBI^ _val1, int _val2){
    
         MiniBI^ _temp=gcnew MiniBI(_val2);
    
         return _val1+_temp;
    
    }
    would the above work correctly? If I have the mutexes only in the methods that return a new reference do I need to use the mutex in the parts that just return a part of the current reference? (in other words read from it). I have been running these classes in simple multithreaded instances without trouble so far, but I have been playing around with vs 2010 and it is pushing them harder, even though I have not been able to point any problems to my classes yet, they do not appear to be thread safe from what I unbderstand so far.

    Thanks in advance,

    Richard
    Last edited by AKRichard; August 13th, 2011 at 03:35 PM. Reason: didnt mean to post it yet

  2. #2
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: A few questions about thread safety

    First I must admit that I can't really claim to be an expert on multithreading myself either, so the following may contain mistakes or omissions that then hopefully get corrected by one of those who know better...

    Quote Originally Posted by AKRichard View Post
    [...] All of the classes are immutable, once the object is created, it never changes that values. The assignment and math operators all create a new object and return that [...].
    I never really thought about that yet, but as to my understanduing, immutable classes are thread-safe per se. However, I've never written a class of which I think I could positively claim its immutability, so I always guarded my objects against multithreading issues (only in case I use them in such a context, of course).

    I just noticed that this really frequent passage from MSDN docs:

    Quote Originally Posted by MSDN
    Thread Safety

    Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

    [...]
    actually is not present in the documentation of System::String, which probably is the most prominent example of an immutable class. (I took the quote from the documentation on one of the generic collections. Maybe it actually isn't as ubiquotions as I perceive it and is just specific to those collections, but I use the generic collections quite often which may have distorted my perception.)

    [...] however, I do not believe that it is thread safe in that if an instance is assigning itself to a new reference and another thread is reading (or worse assigning a different instance to it) the behavior would appear to be unpredictable. After reading quite a few articles on designing thread safety, I think I have an idea of how to approach it, but I do have a few questions to clear up first.
    I believe the immutable object itself to be thread-safe, yet not the tracking handle variable(s) referring to it. So I don't think you need to guard the object itself, but you may need to guard the variables holding its tracking handle or the objects containing these. (However, I have no idea of what you mean by "an instance is assigning itself to a new reference".)

    For example, I know that static methods are shared between all instances, but, are any instance variables created within the method shared also are does each invocation have its own copy? for example:

    Code:
    static MiniBI^ ModPow(MiniBI^ _base, MiniBI^ _exponent, MiniBI^ _modulus){
    
           MiniBI^ _retval=gcnew MiniBI();    //would this variable be shared or would each invocation create its own instance?
    
            .......rest of algorithm
    
          return _retval;
    
    }
    Here you need to make a distinction between the MiniBI instance created inside the static function, the tracking handle local to that function pointing to that instance, _retval, and MiniBI instances and their members in general. The MiniBI instance created in the code snippet is singular (IOW a singleton) and of course any reference to a MiniBI that is obtained by calling ModPow() share the same MiniBI instance. There also is only one instance of _retval holding the tracking handle of that particular singular MiniBI instance. However, should construction of MiniBI objects by client code be allowed at all, of course these objects would not share anything with the instance pointed to by _retval or among each other unless they call ModPow() on their own or otherwise access any other static class members.

    Another question I have is about mutexes. If I create one mutex for the class and call WaitOne() when first entering the method would it allow the same thread to enter a different method within the same class? [...]
    I wouldn't use a Mutex in this scenario at all. Unless you create a separate Mutex for each instance of the class which would be quite tideous, you would be locking on the entire class instead of the individual objects which can be pretty inefficient. For purposes like that I've always used a Monitor which provides a convenient means of locking on the individual objects. There also is the MethodImplAttribute which allows you to actually have the compiler implement the locking for you but I've never used that, among other reasons because I'm not quite certain about the price I'd have to pay for that extra convenience.

    (Actually, the Monitor class can be used to lock on classes instead of objects as well, but I don't want to go too much into detail here.)

    In fact, I have only used mutexes so far for inter-process protection of global resources. Of course these were system-wide (i.e. named) mutexes.

    So would the operator* method let the thread through since it allready has control of the mutex in the Pow method? would it still let it through if another thread had allready called WaitOne() in the operator* before it?
    A given thread can lock on a mutex it already owns any number of times it wants without blocking. However, it needs to later release the mutex the same number of times to make it available to other threads again. The same applies to the Monitor.
    Last edited by Eri523; August 14th, 2011 at 12:02 AM.
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  3. #3
    Join Date
    May 2009
    Posts
    2,413

    Re: A few questions about thread safety

    Quote Originally Posted by AKRichard View Post
    All of the classes are immutable, once the object is created, it never changes that values.
    If a class is immutable it's threadsafe.

  4. #4
    Join Date
    Aug 2009
    Location
    Finally back in Alaska
    Posts
    141

    Re: A few questions about thread safety

    Quote Originally Posted by nuzzle View Post
    If a class is immutable it's threadsafe.
    thats what I had been reading, and all the classes are truly immutable, once an instance is created it never changes, Anytime a change needs to be made, it returns a refernce to a new object. All I was worried about was if a read happened in the middle of an operation working on returning a new object. The read would read an object in a valid state I just wanted to make sure.

    The more I think about it, if 2 different threads where working on making a change to the same object at the same time, both would still create valid objects even though I cant think of why someone would have to different threads update the same object, and if one thread is reading the object in the middle of an operation then that would be a race condition huh? as far as the tracking handles not being thread safe, thats not something I would look to taking care of in the class, that should be taken care of on the consumers end.

    So just because its thread safe is there anything I am overlooking as to synchronization? or anything else that I may not have thought of?

    Thanks,

    Richard

  5. #5
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: A few questions about thread safety

    Quote Originally Posted by AKRichard View Post
    So just because its thread safe is there anything I am overlooking as to synchronization? or anything else that I may not have thought of?
    To start with make sure you understand the rules with regard to sharing resources between threads:

    1) If all threads only access a resource for reading, then no synchronization is required.
    2) If at least one thread accesses the shared resource for writing while other other threads access for reading or writing, then synchronization is required.

    The above rules imply concurrent access from different threads. If your system prevents concurrent access through some other mechanism, then the above rules may not apply.

    So that being said, if you are confident that the objects are immutable, then you probably won't have any issues. I would recommend that you look at the guarding an object at the moment it is being changed (and a new object is being created) to make sure it's thread safe during this time.

    Btw, prefer to use the Monitor class over a Mutex unless you need the cross process capabilities of the mutex. The Monitor class (and it's underlying critical section implementation) is going to be more performant than a Mutex.

  6. #6
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: A few questions about thread safety

    Quote Originally Posted by AKRichard View Post
    as far as the tracking handles not being thread safe, thats not something I would look to taking care of in the class, that should be taken care of on the consumers end.
    Yeah, that's what I meant to say by...

    Quote Originally Posted by me View Post
    I believe the immutable object itself to be thread-safe, yet not the tracking handle variable(s) referring to it. So I don't think you need to guard the object itself, but you may need to guard the variables holding its tracking handle or the objects containing these.
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  7. #7
    Join Date
    Aug 2009
    Location
    Finally back in Alaska
    Posts
    141

    Re: A few questions about thread safety

    Quote Originally Posted by Arjay View Post
    To start with make sure you understand the rules with regard to sharing resources between threads:

    1) If all threads only access a resource for reading, then no synchronization is required.
    2) If at least one thread accesses the shared resource for writing while other other threads access for reading or writing, then synchronization is required.

    The above rules imply concurrent access from different threads. If your system prevents concurrent access through some other mechanism, then the above rules may not apply.

    So that being said, if you are confident that the objects are immutable, then you probably won't have any issues. I would recommend that you look at the guarding an object at the moment it is being changed (and a new object is being created) to make sure it's thread safe during this time.

    Btw, prefer to use the Monitor class over a Mutex unless you need the cross process capabilities of the mutex. The Monitor class (and it's underlying critical section implementation) is going to be more performant than a Mutex.
    but that synchronization would fall to the program creating instances of the class right? (Like what ERI was saying), even if a read occurs while the instance is performing a calculation (Say exponentiation) it would read a valid state since the exponentiation wouldnt return a different value until it had finished and since it returns a new reference, the read would allways read one state or another, not a mixture of the two

  8. #8
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: A few questions about thread safety

    Quote Originally Posted by AKRichard View Post
    but that synchronization would fall to the program creating instances of the class right?
    If the original values can change during creation of the new immutable instance, then you should synchronize while creating the instance.

  9. #9
    Join Date
    May 2009
    Posts
    2,413

    Re: A few questions about thread safety

    Quote Originally Posted by AKRichard View Post
    So just because its thread safe is there anything I am overlooking as to synchronization? or anything else that I may not have thought of?
    Generally object creation is not threadsafe if you,

    1. expose the this pointer from a constructor to another thread, or
    2. use a resource in the constructor that's shared among objects of the class.

    The first you simply avoid by never exposing the this pointer during object creation.

    The second requires that accesses to the shared resource is synchronized or that object creation is synchronized as a whole.

  10. #10
    Join Date
    Aug 2009
    Location
    Finally back in Alaska
    Posts
    141

    Re: A few questions about thread safety

    Quote Originally Posted by nuzzle View Post
    Generally object creation is not threadsafe if you,

    1. expose the this pointer from a constructor to another thread, or
    2. use a resource in the constructor that's shared among objects of the class.

    The first you simply avoid by never exposing the this pointer during object creation.

    The second requires that accesses to the shared resource is synchronized or that object creation is synchronized as a whole.
    I dont have to worry about either one of those problems, I just got done going completely through the entire namespace and believe it is good. Now I can move on to questions about multithreading in particular which Ill do in another post.

    Thanks for taking the time to answer the questions

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured