Search code examples
c++multithreadingproducer-consumerstdatomic

Is it Thread Safe to read from lower index elements of an struct array while it is being filled with data in main thread


Original Question:

I got an array of structs and filling it in a separate thread while reading it in main thread:

struct DataModel MyData[1024];

struct DataModel
{
    bool IsFilled;
    float a;
    float b;
}
  • I have a Thread which is filling the Mydata array from 0 index to the last index(in above it is 1024).

  • Then i get the last filled struct index out from the filling thread.

  • And then i try to read the the values of the element with one index lower than the filled one.

  • Let 's assume that when the 500th element is filled i read the value from 499 element of MyData array, so i assure that i am not reading the array element which is being written.

Q1: Is this thread safe?

Q2: is there chance of occurring undefined behavior or misreading the vales?


Further Edits:

The question was improperly edited to add more details and that's why it introduced inconsistency over answers so i separated the previous edits to improve consistency over answers and accepted answer.

Edit 1: this is a suggestion of the possible implementation. though it may show false results, but just i wanted to ask about thread-safety and and undefined behavior, the following solution may show various result but i was trying to ask about thread safety first.

std::atomic<int> FilledIndex;
    void FillingMyData(struct DataModel myData[])
    {
      for(size_t i = 0; i < 1024; i++)
      {
        myData[i].a = rand();
        myData[i].b = rand();
        myData[i].IsFilled = true;

    FilledIndex = i;
  }
}

int main()
{
     std::thread ReadThread(FillingMyData, MyData);
     while(FilledIndex < 1024)
     {
          std::cout << MyData[FilledIndex].a;
     }
     ReadThread.join();
     return 0;
}

Solution

  • Yes, it is safe to work on separate objects in the same array. Even though an array is an object, it is the elements of the array that we are working on and those are separate objects. As long as you don't read an element the writer is writing to, then there is no data race and the code has defined behavior. You do have synchronization issues with your posted code but the other answers here cover hat those are.

    What can happen here though is what is called false sharing. What happens in these cases is the separate objects are in the same cache line in memory. When on core/thread changes one object, that cache line gets marked as changed. This means the other core/thread has to re-sync that line to pull in any changes which means both cores/threads can't run at the same time. This is a performance penalty only though, and program will still give the correct results, it will just be slower.