Parallel loops in OpenMP parallelise loops over independent iterations by distributing the iteration range across all threads, each thread writing to its own slice of the array. Adding #pragma omp parallel for above the loop enables this pattern, which is the most common in C when each iteration writes to a different output location and doesn't read results that other iterations produce. No synchronisation is needed because the iterations are independent:
#pragma omp parallel for for (int i = 0; i < N; i++) { a[i] = i * 0.5; }
The directive requires the loop to have a countable iteration space and no data dependencies between iterations. Writing to a[i] must not depend on a[i-1] or any other a[j]. Loops with such dependencies require a different strategy (e.g. a scan) or explicit synchronisation.