Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C++ guarantees it is safe to access adjacent elements of an array from two threads

As far as the C++ standard is concerned (C++11 and later, I guess, since before threads were not considered), is it safe to write concurrently to different, possibly adjacent, elements of an array?

For example:

#include <iostream>
#include <thread>

int array[10];

void func(int i) {
   array[i] = 42;
}

int main() 
{
   for(int i = 0; i < 10; ++i) {
      // spawn func(i) on a separate thread
      // (e.g. with std::async, let me skip the details)
   }
   // join

   for(int i = 0; i < 10; ++i) {
      std::cout << array[i] << std::endl; // prints 42?
   }

   return 0;
}

In this case, is it guaranteed by the language that the writes of different elements of the array do not cause race conditions? And is it guaranteed for any type, or are there any requirements for this to be safe?

like image 921
gigabytes Avatar asked Apr 12 '19 08:04

gigabytes


1 Answers

Yes.

From https://en.cppreference.com/w/cpp/language/memory_model:

When an evaluation of an expression writes to a memory location and another evaluation reads or modifies the same memory location, the expressions are said to conflict. A program that has two conflicting evaluations has a data race unless [...]

Then:

A memory location is

  • an object of scalar type (arithmetic type, pointer type, enumeration type, or std::nullptr_t)
  • or the largest contiguous sequence of bit fields of non-zero length

So, if the elements of an array are stored at different memory locations you do not have a conflicting evaluations.

And an array is:

A declaration of the form T a[N];, declares a as an array object that consists of N contiguously allocated objects of type T.

Since two distinct objects cannot have the same address, they and their constituants cannot have the same memory location. Which guarantees satisfaction of the earlier requirement.

Moreover, objects can consist of more than one memory location, so you could even have two threads operate on different members of the same object!

Please note that for your example to be correct, join has to be written correctly as well, but it's not related to adjacent elements of an array, but rather operating on the same one, so I guess it's beyond the scope of the question.


Personal note: Btw. If this wasn't guaranteed, it would seriously limit if not render useless parallel computing in standard library.

like image 168
luk32 Avatar answered Sep 24 '22 06:09

luk32