Search code examples
thread-safetycritical-section

Thread safety question about one container


Let's talk about theory a bit. We have one container, let's call it TMyObj that looks like this:

struct TMyObj{ 
                bool bUpdated;
                bool bUnderUpdate;
             }

Let a class named TMyClass have an array of the container above + 3 helpful functions. One for getting an object to be updated. One for adding update info to a certain object and one for getting an updated object. It's also called in this order. Here's the class

class TMyClass{
  TmyObj entries[];
  TMyObj GetObjToUpdate;
  {
     //Enter critical section
     for(int i=0; i<Length(entries); i++) 
       if(!entries[i].bUnderUpdate)
       { 
         entries[i].bUnderUpdate=true;
         return entries[i];
       }
     //Leave critical section
  }
  //the parameter here is always contained in the Entries array above 
  void AddUpdateInfo(TMyObj obj)
  {
    //Do something...
    //Enter critical section
    if(updateInfoOver) obj.bUpdated=true; //left bUnderUpdate as true so it doesn't bother us
    //Leave critical section
  }
  TmyObj GetUpdatedObj
  {
    //<-------- here
    for(int i=0; i<Length(entrues); i++)
      if(entries[i].bUpdated) then return entries[i];
    //<-------- and here?
  }
}

Now imagine 5+ threads using the first two and another one for using the last function(getUpdadtedObj) on one instance of the class above.

Question: Will it be thread-safe if there's no critical section in the last function?


Solution

  • Given your sample code, it appears that it would be thread-safe for a read. This is assuming entries[] is a fixed size. If you are simply iterating over a fixed collection, there is no reason that the size of the collection should be modified, therefore making a thread-safe read ok.

    The only thing I could see is that the result might be out of date. The problem comes from a call to GetUpdatedObj -- Thread A might not see an update to entries[0] during the life-cycle of

    for(int i=0; i<Length(entrues); i++)
          if(entries[i].bUpdated) then return entries[i];
    

    if Thread B comes along and updates entries[0] while i > 0 -- it all depends if that is considered acceptable or not.